网上的东西不可靠啊。。。要么就泛泛而谈要么就是代码有问题。。。。。。
import socket import select import queue serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_address = ("127.0.0.1", 8888) serversocket.bind(server_address); serversocket.listen(10) print('服务器启动,监听IP:', server_address) serversocket.setblocking(False) timeout = 10 epoll = select.epoll() epoll.register(serversocket.fileno(),select.EPOLLIN) message_queues = {} fd_to_socket = {serversocket.fileno():serversocket,} while True: print('等待活动链接 ') events = epoll.poll(timeout) if not events: print('epoll超时,重新轮训') continue print('有', len(events) , '个新事件需要处理, fd_to_socket:', len(fd_to_socket)) for fd, event in events: socket = fd_to_socket[fd] if socket == serversocket : connection, address = serversocket.accept() print('新链接' , address) connection.setblocking(False) epoll.register(connection.fileno(),select.EPOLLIN) fd_to_socket[connection.fileno()] = connection #print('fd1:%s fd2:%s' % (fd, connection.fileno())) message_queues[connection] = queue.Queue() print(fd_to_socket) elif event & select.EPOLLHUP: print('Client Close %s' % fd) epoll.unregister(fd) fd_to_socket[fd].close() del fd_to_socket[fd] elif event & select.EPOLLIN: data = socket.recv(1024) if data: print('收到数据: ', data, '客户端: ', socket.getpeername()) message_queues[socket].put(data) epoll.modify(fd,select.EPOLLOUT) else: epoll.modify(fd,select.EPOLLHUP) print('Client Close %s' % fd) epoll.unregister(fd) fd_to_socket[fd].close() del fd_to_socket[fd] elif event & select.EPOLLOUT: try: msg = message_queues[socket].get_nowait() socket.send(msg) except queue.Empty: print(socket.getpeername, " queue empty") epoll.modify(fd, select.EPOLLIN) epoll.unregister(serversocket.fileno()) epoll.close() serversocket.close()
按照我的理解,epoll模型是以事件为触发的。一旦一个fd上有任何的事件发生,epoll就会解除阻塞,那么接下来就要依据其fd找出我们要的那个socket对象,接着需要依据EPOLL消息的类型制定响应的策略。
不过我还有一事不解,为什么在telnet之后的 被识别为无效之后并没有正确的将event modify到EPOLLHUP的事件上,非常诡异,希望知道的大神指点迷津。