Skip to content

Instantly share code, notes, and snippets.

@gordinmitya
Last active October 1, 2019 12:36
Show Gist options
  • Save gordinmitya/349f4abdc6b16dc163fa39b55544fd34 to your computer and use it in GitHub Desktop.
Save gordinmitya/349f4abdc6b16dc163fa39b55544fd34 to your computer and use it in GitHub Desktop.
Simple python socket chat. One thread per client. Use telnet to join.
import socket
from threading import Thread
clients = []
# Thread to listen one particular client
class ClientListener(Thread):
def __init__(self, name: str, sock: socket.socket):
super().__init__(daemon=True)
self.sock = sock
self.name = name
# add 'me> ' to sended message
def _clear_echo(self, data):
# \033[F – symbol to move the cursor at the beginning of current line (Ctrl+A)
# \033[K – symbol to clear everything till the end of current line (Ctrl+K)
self.sock.sendall('\033[F\033[K'.encode())
data = 'me> '.encode() + data
# send the message back to user
self.sock.sendall(data)
# broadcast the message with name prefix eg: 'u1> '
def _broadcast(self, data):
data = (self.name + '> ').encode() + data
for u in clients:
# send to everyone except current client
if u == self.sock:
continue
u.sendall(data)
# clean up
def _close(self):
clients.remove(self.sock)
self.sock.close()
print(self.name + ' disconnected')
def run(self):
while True:
# try to read 1024 bytes from user
# this is blocking call, thread will be paused here
data = self.sock.recv(1024)
if data:
self._clear_echo(data)
self._broadcast(data)
else:
# if we got no data – client has disconnected
self._close()
# finish the thread
return
def main():
next_name = 1
# AF_INET – IPv4, SOCK_STREAM – TCP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# reuse address; in OS address will be reserved after app closed for a while
# so if we close and imidiatly start server again – we'll get error
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# listen to all interfaces at 8800 port
sock.bind(('', 8800))
sock.listen()
while True:
# blocking call, waiting for new client to connect
con, addr = sock.accept()
clients.append(con)
name = 'u' + str(next_name)
next_name += 1
print(str(addr) + ' connected as ' + name)
# start new thread to deal with client
ClientListener(name, con).start()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment