Last active
February 9, 2023 12:33
-
-
Save gregvish/7665915 to your computer and use it in GitHub Desktop.
Python 3.4 asyncio chat server example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from socket import socket, SO_REUSEADDR, SOL_SOCKET | |
from asyncio import Task, coroutine, get_event_loop | |
class Peer(object): | |
def __init__(self, server, sock, name): | |
self.loop = server.loop | |
self.name = name | |
self._sock = sock | |
self._server = server | |
Task(self._peer_handler()) | |
def send(self, data): | |
return self.loop.sock_sendall(self._sock, data.encode('utf8')) | |
@coroutine | |
def _peer_handler(self): | |
try: | |
yield from self._peer_loop() | |
except IOError: | |
pass | |
finally: | |
self._server.remove(self) | |
@coroutine | |
def _peer_loop(self): | |
while True: | |
buf = yield from self.loop.sock_recv(self._sock, 1024) | |
if buf == b'': | |
break | |
self._server.broadcast('%s: %s' % (self.name, buf.decode('utf8'))) | |
class Server(object): | |
def __init__(self, loop, port): | |
self.loop = loop | |
self._serv_sock = socket() | |
self._serv_sock.setblocking(0) | |
self._serv_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) | |
self._serv_sock.bind(('',port)) | |
self._serv_sock.listen(5) | |
self._peers = [] | |
Task(self._server()) | |
def remove(self, peer): | |
self._peers.remove(peer) | |
self.broadcast('Peer %s quit!\n' % (peer.name,)) | |
def broadcast(self, message): | |
for peer in self._peers: | |
peer.send(message) | |
@coroutine | |
def _server(self): | |
while True: | |
peer_sock, peer_name = yield from self.loop.sock_accept(self._serv_sock) | |
peer_sock.setblocking(0) | |
peer = Peer(self, peer_sock, peer_name) | |
self._peers.append(peer) | |
self.broadcast('Peer %s connected!\n' % (peer.name,)) | |
def main(): | |
loop = get_event_loop() | |
Server(loop, 1234) | |
loop.run_forever() | |
if __name__ == '__main__': | |
main() |
Greg do you mind if this forms the basis of psyrcd-0.21? Project currently lives here: https://github.com/LukeB42/Psyrcd
Cheers
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
asyncio already brings the whole socket stuff with it, so you can cut that out. Plus using the power of the Protocol class does shorten the code (not perfect, just for demonstration purposes):