how to use epoll with python
1 import socket, select 2 3 EOL1 = b'\n\n' 4 EOL2 = b'\n\r\n' 5 response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n' 6 response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n' 7 response += b'Hello, world!' 8 9 serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10 serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 11 serversocket.bind(('0.0.0.0', 8080)) 12 serversocket.listen(1) 13 serversocket.setblocking(0) 14 15 epoll = select.epoll() 16 epoll.register(serversocket.fileno(), select.EPOLLIN) 17 18 try: 19 connections = {}; requests = {}; responses = {} 20 while True: 21 events = epoll.poll(1) 22 for fileno, event in events: 23 if fileno == serversocket.fileno(): 24 connection, address = serversocket.accept() 25 connection.setblocking(0) 26 epoll.register(connection.fileno(), select.EPOLLIN) 27 connections[connection.fileno()] = connection 28 requests[connection.fileno()] = b'' 29 responses[connection.fileno()] = response 30 elif event & select.EPOLLIN: 31 requests[fileno] += connections[fileno].recv(1024) 32 if EOL1 in requests[fileno] or EOL2 in requests[fileno]: 33 epoll.modify(fileno, select.EPOLLOUT) 34 print('-'*40 + '\n' + requests[fileno].decode()[:-2]) 35 elif event & select.EPOLLOUT: 36 byteswritten = connections[fileno].send(responses[fileno]) 37 responses[fileno] = responses[fileno][byteswritten:] 38 if len(responses[fileno]) == 0: 39 epoll.modify(fileno, 0) 40 connections[fileno].shutdown(socket.SHUT_RDWR) 41 elif event & select.EPOLLHUP: 42 epoll.unregister(fileno) 43 connections[fileno].close() 44 del connections[fileno] 45 finally: 46 epoll.unregister(serversocket.fileno()) 47 epoll.close() 48 serversocket.close() EPOLLERR Error condition happened on the associated file descriptor. This event is also reported for the write end of a pipe when the read end has been closed. epoll_wait(2) will always report for this event; it is not necessary to set it in events. EPOLLHUP Hang up happened on the associated file descriptor. epoll_wait(2) will always wait for this event; it is not necessary to set it in events. Line 40: A socket shutdown is optional if a connection is closed explicitly. This example program uses it in order to cause the client to shutdown first. The shutdown call informs the client socket that no more data should be sent or received and will cause a well-behaved client to close the socket connection from it's end. Line 41: The HUP (hang-up) event indicates that the client socket has been disconnected (i.e. closed), so this end is closed as well. There is no need to register interest in HUP events. They are always indicated on sockets that are registered with the epoll object. socket.shutdown(how) Shut down one or both halves of the connection. If how is SHUT_RD, further receives are disallowed. If how is SHUT_WR, further sends are disallowed. If how is SHUT_RDWR, further sends and receives are disallowed. Depending on the platform, shutting down one half of the connection can also close the opposite half (e.g. on Mac OS X, shutdown(SHUT_WR) does not allow further reads on the other end of the connection).