为了节省篇幅,这里直接使用了全局变量,也没有处理异常。程序的核心仍然是事件循环,与前面不同的是,事件的处理通过 `handlers`转发到各个函数中,不再集中在一坨。例如`listening fd`的处理函数是`handle_accept`,它会注册客户连接的handler。普通客户连接的处理函数是`handle_request`,其中又把连接断开和数据到达这两个事件分开,后者由`handle_input` 处理。业务逻辑位于单独的 `handle_input` 函数,实现了分离。 ```python server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(('', 2007)) server_socket.listen(5) # serversocket.setblocking(0) poll = select.poll() # epoll() should work the same connections = {} handlers = {} def handle_input(socket, data): socket.send(data) # sendall() partial? def handle_request(fileno, event): if event & select.POLLIN: client_socket = connections[fileno] data = client_socket.recv(4096) if data: handle_input(client_socket, data) else: poll.unregister(fileno) client_socket.close() del connections[fileno] del handlers[fileno] def handle_accept(fileno, event): (client_socket, client_address) = server_socket.accept() print "got connection from", client_address # client_socket.setblocking(0) poll.register(client_socket.fileno(), select.POLLIN) connections[client_socket.fileno()] = client_socket handlers[client_socket.fileno()] = handle_request poll.register(server_socket.fileno(), select.POLLIN) handlers[server_socket.fileno()] = handle_accept while True: events = poll.poll(10000) # 10 seconds for fileno, event in events: handler = handlers[fileno] handler(fileno, event) ``` 如果要改成聊天服务,重新定义 `handle_input` 函数即可,程序的其余部分保持不变。 ```python $ diff echo-reactor.py chat-reactor.py -U1 def handle_input(socket, data): - socket.send(data) # sendall() partial? + for (fd, other_socket) in connections.iteritems(): + if other_socket != socket: + other_socket.send(data) # sendall() partial? ``` 必须说明的是,完善的`非阻塞 IO 网络库`远比上面的玩具代码复杂,需要考虑各 种错误场景。特别是要真正接管数据的收发,而不是像上面的示例那样直接在事件处 理回调函数中发送网络数据。 注意在使用`非阻塞 IO` +`事件驱动方式`编程的时候,一定要注意避免在事件回调 中执行耗时的操作,包括`阻塞 IO` 等,否则会影响程序的响应。这和 `Windows GUI` 消息循环非常类似。 -------------------------- -----文章引用自([Linux 多线程服务端编程:使用 muduo C++ 网络库 (excerpt) http://www.chenshuo.com/book/](http://www.chenshuo.com/book/))