From 219ffcce0fa211650b20668febe4b55a259d2f6d Mon Sep 17 00:00:00 2001 From: Rik Veenboer Date: Tue, 2 Jun 2015 21:20:49 +0200 Subject: [PATCH] add example using select/asyncore from http://etutorials.org/Programming/Python+tutorial/Part+IV+Network+and+Web+Programming/Chapter+19.+Sockets+and+Server-Side+Network+Protocol+Modules/19.3+Event-Driven+Socket+Programs/ --- TcpClient.py | 13 ++++++++++ asyncore/TcpServer.py | 24 ++++++++++++++++++ select/TcpServer.py | 58 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 TcpClient.py create mode 100644 asyncore/TcpServer.py create mode 100644 select/TcpServer.py diff --git a/TcpClient.py b/TcpClient.py new file mode 100644 index 0000000..367a1fb --- /dev/null +++ b/TcpClient.py @@ -0,0 +1,13 @@ +import socket +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect(('localhost', 8881)) +print "Connected to server" +data = """A few lines of data +to test the operation +of both server and client.""" +for line in data.splitlines( ): + sock.sendall(line+'\n') + print "Sent:", line + response = sock.recv(8192) + print "Received:", response +sock.close( ) \ No newline at end of file diff --git a/asyncore/TcpServer.py b/asyncore/TcpServer.py new file mode 100644 index 0000000..1c1de9f --- /dev/null +++ b/asyncore/TcpServer.py @@ -0,0 +1,24 @@ +import asyncore +import socket + +class MainServerSocket(asyncore.dispatcher): + def __init__(self, port): + asyncore.dispatcher.__init__(self) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.bind(('',port)) + self.listen(5) + def handle_accept(self): + newSocket, address = self.accept( ) + print "Connected from", address + SecondaryServerSocket(newSocket) + +class SecondaryServerSocket(asyncore.dispatcher_with_send): + def handle_read(self): + receivedData = self.recv(8192) + if receivedData: self.send(receivedData) + else: self.close( ) + def handle_close(self): + print "Disconnected from", self.getpeername( ) + +MainServerSocket(8881) +asyncore.loop( ) \ No newline at end of file diff --git a/select/TcpServer.py b/select/TcpServer.py new file mode 100644 index 0000000..2a325eb --- /dev/null +++ b/select/TcpServer.py @@ -0,0 +1,58 @@ +import socket +import select +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.bind(('', 8881)) +sock.listen(5) + +# lists of sockets to watch for input and output events +ins = [sock] +ous = [] +# mapping socket -> data to send on that socket when feasible +data = {} +# mapping socket -> (host, port) on which the client is running +adrs = {} + +try: + while True: + i, o, e = select.select(ins, ous, []) # no excepts nor timeout + for x in i: + if x is sock: + # input event on sock means client trying to connect + newSocket, address = sock.accept( ) + print "Connected from", address + ins.append(newSocket) + adrs[newSocket] = address + else: + # other input events mean data arrived, or disconnections + newdata = x.recv(8192) + if newdata: + # data arrived, prepare and queue the response to it + print "%d bytes from %s" % (len(newdata), adrs[x]) + data[x] = data.get(x, '') + newdata + if x not in ous: ous.append(x) + else: + # a disconnect, give a message and clean up + print "disconnected from", adrs[x] + del adrs[x] + try: ous.remove(x) + except ValueError: pass + x.close( ) + for x in o: + # output events always mean we can send some data + tosend = data.get(x) + if tosend: + nsent = x.send(tosend) + print "%d bytes to %s" % (nsent, adrs[x]) + # remember data still to be sent, if any + tosend = tosend[nsent:] + if tosend: + print "%d bytes remain for %s" % (len(tosend), adrs[x]) + data[x] = tosend + else: + try: del data[x] + except KeyError: pass + ous.remove(x) + print "No data currently remain for", adrs[x] +finally: + sock.close( ) +