├── LICENSE.md ├── p2p.py ├── Client.py ├── README.md └── Server.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | #The MIT License (MIT) 2 | 3 | ###Copyright (c) 2015 Rakshith G 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /p2p.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import socket 4 | import sys 5 | import time 6 | import threading 7 | class Server(threading.Thread): 8 | def run(self): 9 | self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 10 | print "Server started successfully\n" 11 | hostname='' 12 | port=51412 13 | self.sock.bind((hostname,port)) 14 | self.sock.listen(1) 15 | print "Listening on port %d\n" %port 16 | #time.sleep(2) 17 | (clientname,address)=self.sock.accept() 18 | print "Connection from %s\n" % str(address) 19 | while 1: 20 | chunk=clientname.recv(4096) 21 | print str(address)+':'+chunk 22 | 23 | class Client(threading.Thread): 24 | def connect(self,host,port): 25 | self.sock.connect((host,port)) 26 | def client(self,host,port,msg): 27 | sent=self.sock.send(msg) 28 | print "Sent\n" 29 | def run(self): 30 | self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 31 | try: 32 | host=raw_input("Enter the hostname\n>>") 33 | port=int(raw_input("Enter the port\n>>")) 34 | except EOFError: 35 | print "Error" 36 | return 1 37 | 38 | print "Connecting\n" 39 | s='' 40 | self.connect(host,port) 41 | print "Connected\n" 42 | while 1: 43 | print "Waiting for message\n" 44 | msg=raw_input('>>') 45 | if msg=='exit': 46 | break 47 | if msg=='': 48 | continue 49 | print "Sending\n" 50 | self.client(host,port,msg) 51 | return(1) 52 | if __name__=='__main__': 53 | srv=Server() 54 | srv.daemon=True 55 | print "Starting server" 56 | srv.start() 57 | time.sleep(1) 58 | print "Starting client" 59 | cli=Client() 60 | print "Started successfully" 61 | cli.start() 62 | 63 | 64 | -------------------------------------------------------------------------------- /Client.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import socket 4 | import sys 5 | import time 6 | import threading 7 | import select 8 | import traceback 9 | class Server(threading.Thread): 10 | def initialise(self,receive): 11 | self.receive=receive 12 | def run(self): 13 | lis=[] 14 | lis.append(self.receive) 15 | while 1: 16 | read,write,err=select.select(lis,[],[]) 17 | for item in read: 18 | try: 19 | s=item.recv(1024) 20 | if s!='': 21 | chunk=s 22 | print str('')+':'+chunk 23 | except: 24 | traceback.print_exc(file=sys.stdout) 25 | break 26 | 27 | class Client(threading.Thread): 28 | def connect(self,host,port): 29 | self.sock.connect((host,port)) 30 | def client(self,host,port,msg): 31 | sent=self.sock.send(msg) 32 | #print "Sent\n" 33 | def run(self): 34 | self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 35 | self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 36 | try: 37 | host=raw_input("Enter the hostname\n>>") 38 | port=int(raw_input("Enter the port\n>>")) 39 | except EOFError: 40 | print "Error" 41 | return 1 42 | 43 | print "Connecting\n" 44 | s='' 45 | self.connect(host,port) 46 | print "Connected\n" 47 | receive=self.sock 48 | time.sleep(1) 49 | srv=Server() 50 | srv.initialise(receive) 51 | srv.daemon=True 52 | print "Starting service" 53 | srv.start() 54 | while 1: 55 | #print "Waiting for message\n" 56 | msg=raw_input('>>') 57 | if msg=='exit': 58 | break 59 | if msg=='': 60 | continue 61 | #print "Sending\n" 62 | self.client(host,port,msg) 63 | return(1) 64 | if __name__=='__main__': 65 | print "Starting client" 66 | cli=Client() 67 | cli.start() 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # P2P Chat App 2 | #### A simple to use chat program that uses sockets and multi-threading 3 | 4 | This is a p2p chat program written in python. The traditional client server based chat is also supported 5 | ## 1. Getting started 6 | Start the server using 7 | ```sh 8 | $ python Server.py 9 | ```` 10 | The clients can connect to the server through client.py 11 | ```sh 12 | $ python Client.py 13 | ```` 14 | --- 15 | The p2p version can be started using the command 16 | ```sh 17 | $ python p2p.py 18 | ```` 19 | ---- 20 | Alternatively, it can be run from the terminal itself. 21 | ####1. Make the files executable 22 | ```sh 23 | $chmod u+x Server.py Client.py p2p.py 24 | ```` 25 | ####2. Run the program 26 | ````sh 27 | $ ./Server.py 28 | ```` 29 | ````sh 30 | $ ./Client.py 31 | ```` 32 | ````sh 33 | $ ./p2p.py 34 | ```` 35 | ---- 36 | The client asks for the hostname and the port on which the server is listening. Then an attempt is made to connect to the server. If everything is all right, the client should prompt you to start typing your messages. Else an exception is thrown. 37 | 38 | ##2. Things to be implemented yet 39 | - General exception handling 40 | - Some more polishing 41 | - Build a gui ;) 42 | 43 | ##3. General 44 | Feel free to report bugs. Or shoot an e-mail to hehaichi@gmail.com 45 | 46 | ##4. License 47 | 48 | This work is licensed with the MIT license 49 | 50 | ####The MIT License (MIT) 51 | Copyright (c) 2015 Rakshith G 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | -------------------------------------------------------------------------------- /Server.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import socket 4 | import sys, traceback 5 | import threading 6 | import thread 7 | import select 8 | SOCKET_LIST=[] 9 | TO_BE_SENT=[] 10 | SENT_BY={} 11 | class Server(threading.Thread): 12 | 13 | def init(self): 14 | self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 15 | self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 16 | self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 17 | self.sock.bind(('',5535)) 18 | self.sock.listen(2) 19 | SOCKET_LIST.append(self.sock) 20 | print "Server started on port 5535" 21 | 22 | def run(self): 23 | while 1: 24 | read,write,err=select.select(SOCKET_LIST,[],[],0) 25 | for sock in read: 26 | if sock==self.sock: 27 | sockfd,addr=self.sock.accept() 28 | print str(addr) 29 | SOCKET_LIST.append(sockfd) 30 | print SOCKET_LIST[len(SOCKET_LIST)-1] 31 | else: 32 | try: 33 | s=sock.recv(1024) 34 | if s=='': 35 | print str(sock.getpeername()) 36 | continue 37 | else: 38 | TO_BE_SENT.append(s) 39 | SENT_BY[s]=(str(sock.getpeername())) 40 | except: 41 | print str(sock.getpeername()) 42 | 43 | 44 | class handle_connections(threading.Thread): 45 | def run(self): 46 | while 1: 47 | read,write,err=select.select([],SOCKET_LIST,[],0) 48 | for items in TO_BE_SENT: 49 | for s in write: 50 | try: 51 | if(str(s.getpeername()) == SENT_BY[items]): 52 | print("Ignoring %s"%(str(s.getpeername()))) 53 | continue 54 | print "Sending to %s"%(str(s.getpeername())) 55 | s.send(items) 56 | 57 | except: 58 | traceback.print_exc(file=sys.stdout) 59 | TO_BE_SENT.remove(items) 60 | del(SENT_BY[items]) 61 | 62 | 63 | 64 | if __name__=='__main__': 65 | srv=Server() 66 | srv.init() 67 | srv.start() 68 | print SOCKET_LIST 69 | handle=handle_connections() 70 | handle.start() 71 | 72 | --------------------------------------------------------------------------------