赞
踩
原文
阻塞模式与非阻塞模式
阻塞模式 程序碰到了一些耗时操作,无法继续向下走。
例如在socket编程中,例如在send()即发送信息过程中,可能对方已经断开,可能网络等原因导致信息传递不通畅;在客户端的connect()函数中,可能地址不可达等原因。这些情况在阻塞模式中会造成线程中断等待,导致无法进行下一步操作,等超过一个固定时间还没有完成之后会产生异常。但是这种阻塞通常用于确定的几个连接地址并且必须准确连接上。
非阻塞模式 当程序碰到耗时操作,分发给别的线程,主线程继续执行。
例如在socket编程中,在send()或connect()函数中,程序会抛出异常10035,在非阻塞模式下无法完成耗时操作,但是程序会继续走下去,不会阻塞到当前的程序。那么,怎么判断什么时候程序完成这些耗时操作呢?select闪亮登场。
Python网络编程-IO阻塞与非阻塞及多路复用
基于select的网络编程
在python中,select函数是一个队底层操作系统直接访问的接口,它用来监控sockets、files和pipse,等待IO完成。当有可读、可写或者是异常事件产生时,select函数可以监控到。
r, w, e, = select.select(rlist, wlist, xlist[, timeout]) 传递三个参数,一个为输入而观察的文件对象列表,一个为输出而观察的文件对象列表和一个观察错误异常的文件列表。第四个是一个可选参数,表示超时秒数。这个就是系统级别的阻塞,如果监控到事件会直接传递到这里。
具体的客户端非阻塞连接如下,使用的是python3.6
# -*- coding: UTF-8 -*- # python使用select进行非阻塞模式编程,客户端程序 import socket import select sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 生成socket sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 不经过WAIT_TIME,直接关闭 sock.setblocking(False) # 设置非阻塞编程 try: # sock.connect(("google.com", 80)) sock.connect(("192.168.1.106", 789)) except Exception as e: print(e) r_inputs = set() r_inputs.add(sock) w_inputs = set() w_inputs.add(sock) e_inputs = set() e_inputs.add(sock) while True: try: r_list, w_list, e_list = select.select(r_inputs, w_inputs, e_inputs, 1) print("r") # 产生了可读事件,即服务端发送信息 for event in r_list: try: data = event.recv(1024) except Exception as e: print(e) if data: print(data) print("收到信息") else: print("远程断开连接") r_inputs.clear() print("w") if len(w_list) > 0: # 产生了可写的事件,即连接完成 print(w_list) w_inputs.clear() # 当连接完成之后,清除掉完成连接的socket print("e") if len(e_list) > 0: # 产生了错误的事件,即连接错误 print(e_list) e_inputs.clear() # 当连接有错误发生时,清除掉发生错误的socket except OSError as e: print(e)
python的select注意事项
除了select,还有什么提高效率的神器
select,poll,epoll优缺点及比较
深度理解select、poll和epoll
通过上述文章可知效率对比 epoll > poll > select
但是在windows系统上只有select,所以常常用以下判断
if hasattr(select, 'epoll'):
self._impl = select.epoll()
model = 'epoll'
elif hasattr(select, 'kqueue'):
self._impl = KqueueLoop()
model = 'kqueue'
elif hasattr(select, 'select'):
self._impl = SelectLoop()
model = 'select'
切记如果在非阻塞情况下缠上了10035的错误,那是正常反应,我们只需用select进行获取即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。