Python异步非阻塞IO多路复用Select/Poll/Epoll使用
来源:互联网 发布:郑州淘宝网店加盟骗局 编辑:程序博客网 时间:2024/05/23 11:54
下面记录下分别基于Select/Poll/Epoll的echo server实现。Python Select Server,可监控事件数量有限制:#!/usr/bin/python# -*- coding: utf-8 -*-importselectimportsocketimportQueue server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.setblocking(False)server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR , 1)server_address=('192.168.1.5',8080)server.bind(server_address)server.listen(10) #select轮询等待读socket集合inputs=[server]#select轮询等待写socket集合outputs=[]message_queues={}#select超时时间timeout=20 whileTrue: print"等待活动连接......" readable , writable , exceptional =select.select(inputs, outputs, inputs, timeout) ifnot (readable orwritable orexceptional) : print"select超时无活动连接,重新select...... " continue; #循环可读事件 fors inreadable : #如果是server监听的socket ifs isserver: #同意连接 connection, client_address =s.accept() print"新连接: ", client_address connection.setblocking(0) #将连接加入到select可读事件队列 inputs.append(connection) #新建连接为key的字典,写回读取到的消息 message_queues[connection]=Queue.Queue() else: #不是本机监听就是客户端发来的消息 data=s.recv(1024) ifdata : print"收到数据:" , data , "客户端:",s.getpeername() message_queues[s].put(data) ifs notin outputs: #将读取到的socket加入到可写事件队列 outputs.append(s) else: #空白消息,关闭连接 print"关闭连接:", client_address ifs inoutputs : outputs.remove(s) inputs.remove(s) s.close() delmessage_queues[s] fors inwritable: try: msg=message_queues[s].get_nowait() exceptQueue.Empty: print"连接:" , s.getpeername() , '消息队列为空' outputs.remove(s) else: print"发送数据:" , msg , "到", s.getpeername() s.send(msg) fors inexceptional: print"异常连接:", s.getpeername() inputs.remove(s) ifs inoutputs: outputs.remove(s) s.close() delmessage_queues[s]Python Poll Server,Select升级版,无可监控事件数量限制,还是要轮询所有事件:#!/usr/bin/python# -*- coding: utf-8 -*-importsocketimportselectimportQueue server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)server.setblocking(False)server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)server_address=("192.168.1.5",8080)server.bind(server_address)server.listen(5)print "服务器启动成功,监听IP:" , server_addressmessage_queues={}#超时,毫秒timeout=5000#监听哪些事件READ_ONLY=( select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR)READ_WRITE=(READ_ONLY|select.POLLOUT)#新建轮询事件对象poller=select.poll()#注册本机监听socket到等待可读事件事件集合poller.register(server,READ_ONLY)#文件描述符到socket映射fd_to_socket={server.fileno():server,}whileTrue: print"等待活动连接......" #轮询注册的事件集合 events=poller.poll(timeout) ifnot events: print"poll超时,无活动连接,重新poll......" continue print"有" , len(events),"个新事件,开始处理......" forfd ,flag inevents: s=fd_to_socket[fd] #可读事件 ifflag & (select.POLLIN | select.POLLPRI) : ifs isserver : #如果socket是监听的server代表有新连接 connection , client_address =s.accept() print"新连接:" , client_address connection.setblocking(False) fd_to_socket[connection.fileno()]=connection #加入到等待读事件集合 poller.register(connection,READ_ONLY) message_queues[connection] =Queue.Queue() else: #接收客户端发送的数据 data=s.recv(1024) ifdata: print"收到数据:" , data , "客户端:", s.getpeername() message_queues[s].put(data) #修改读取到消息的连接到等待写事件集合 poller.modify(s,READ_WRITE) else: # Close the connection print" closing" , s.getpeername() # Stop listening for input on the connection poller.unregister(s) s.close() delmessage_queues[s] #连接关闭事件 elifflag & select.POLLHUP : print" Closing ", s.getpeername() ,"(HUP)" poller.unregister(s) s.close() #可写事件 elifflag & select.POLLOUT : try: msg=message_queues[s].get_nowait() exceptQueue.Empty: prints.getpeername() , " queue empty" poller.modify(s,READ_ONLY) else: print"发送数据:" , data , "客户端:", s.getpeername() s.send(msg) #异常事件 elifflag & select.POLLERR: print" exception on" , s.getpeername() poller.unregister(s) s.close() delmessage_queues[s]Python Epoll Server,基于回调的事件通知模式,轻松管理大量连接:#!/usr/bin/python# -*- coding: utf-8 -*-importsocket, selectimportQueue serversocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)server_address=("192.168.1.5",8080)serversocket.bind(server_address)serversocket.listen(1)print "服务器启动成功,监听IP:" , server_addressserversocket.setblocking(0)timeout=10#新建epoll事件对象,后续要监控的事件添加到其中epoll=select.epoll()#添加服务器监听fd到等待读事件集合epoll.register(serversocket.fileno(), select.EPOLLIN)message_queues={} fd_to_socket={serversocket.fileno():serversocket,}whileTrue: print"等待活动连接......" #轮询注册的事件集合 events=epoll.poll(timeout) ifnot events: print"epoll超时无活动连接,重新轮询......" continue print"有" , len(events),"个新事件,开始处理......" forfd, event inevents: socket=fd_to_socket[fd] #可读事件 ifevent & select.EPOLLIN: #如果活动socket为服务器所监听,有新连接 ifsocket ==serversocket: connection, address =serversocket.accept() print"新连接:" , address connection.setblocking(0) #注册新连接fd到待读事件集合 epoll.register(connection.fileno(), select.EPOLLIN) fd_to_socket[connection.fileno()]=connection message_queues[connection] =Queue.Queue() #否则为客户端发送的数据 else: data=socket.recv(1024) ifdata: print"收到数据:" , data , "客户端:", socket.getpeername() message_queues[socket].put(data) #修改读取到消息的连接到等待写事件集合 epoll.modify(fd, select.EPOLLOUT) #可写事件 elifevent & select.EPOLLOUT: try: msg=message_queues[socket].get_nowait() exceptQueue.Empty: printsocket.getpeername() , " queue empty" epoll.modify(fd, select.EPOLLIN) else: print"发送数据:" , data , "客户端:", socket.getpeername() socket.send(msg) #关闭事件 elifevent & select.EPOLLHUP: epoll.unregister(fd) fd_to_socket[fd].close() delfd_to_socket[fd]epoll.unregister(serversocket.fileno())epoll.close()serversocket.close()
0 0
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用
- IO-同步异步,阻塞非阻塞,select, poll , epoll
- python# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selector
- IO多路复用(select poll epoll)
- IO多路复用:select、poll、epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步、I/O、select、poll、epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 阻塞、非阻塞、异步、同步以及select/poll和epoll
- 为什么要使用MapReduce?
- 程序猿职场分享(转至Jhuster)
- MVVM使用简介
- 自己设计网络爬虫的乱码问题
- JAVA环境的搭建
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用
- 使用xutils第三方库实现联网请求
- 红黑树 操作
- 静态成员函数和非静态成员函数的区别
- 视频中的关键帧
- android获取本地的ip地址工具类
- Linux下的split 命令(将一个大文件根据行数平均分成若干个小文件)
- 快速排序的改进方法
- Java学习笔记161123