Python利用选择器模块实现非阻塞式编程

  

Python利用选择器模块实现非阻塞式编程?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

前面介绍的插座都是采用阻塞方式进行通信的,当程序调用recv()方法从套接字中读取数据时,如果没有读取到有效的数据,当前线程就会被阻塞。为了解决这个问题,上面程序采用了多线程并发编程,即服务器端为每个客户端连接都启动一个单独的线程,不同的线程负责对应的套接字的通信工作。

通过选择器模块允许插座以非阻塞方式进行通信,选择器相当于一个事件注册中心,程序只要将套接字的所有事件注册给选择器管理,当选择器检测到套接字中的特定事件之后,程序就调用相应的监听方法进行处理。

选择器主要支持两种事件:

选择器。EVENT_READ:当插座有数据可读时触发该事件。当有客户端连接进来时也会触发该事件。

选择器。EVENT_WRITE:当插座将要写数据时触发该事件。

使用选择器实现非阻塞式编程的步骤大致如下:

创建选择器对象。

通过选择器对象为套接字的选择器。EVENT_READ或选择器。EVENT_WRITE事件注册监听器函数。每当插座有数据需要读写时,系统负责触发所注册的监昕器函数。

在监听器函数中处理插座通信。

下面程序使用选择器模块实现非阻塞式通信的服务器端:

import 选择器,插座      #,创建默认的选择器对象   时间=sel  selectors.DefaultSelector ()   #,负责监听”有数据可读”事件的函数   def 阅读(sk电讯,面具):   ,,,试一试:   ,,,,,,,#,读取数据   ,,,,,,,data =, skt.recv (1024)   ,,,,,,,if 数据:   ,,,,,,,,,,,#,将读取的数据采用循环向每个插座发送一次   ,,,,,,,,,,,for  s 拷贝socket_list:   ,,,,,,,,,,,,,,,s.send(数据),,#,Hope  it 赢得# 39;t 块   ,,,,,,,其他的:   ,,,,,,,,,,,#,如果该套接字已被对方关闭,关闭该套接字,   ,,,,,,,,,,,#,并从socket_list列表中删除   ,,,,,,,,,,,印刷(& # 39;关闭& # 39;,,sk电讯)   ,,,,,,,,,,,sel.unregister (sk电讯)   ,,,,,,,,,,,skt.close ()   ,,,,,,,,,,,socket_list.remove (sk电讯)   ,,,#,如果捕捉到异常,,将该套接字关闭,并从socket_list列表中删除   ,,,除了:   ,,,,,,,印刷(& # 39;关闭& # 39;,,sk电讯)   ,,,,,,,sel.unregister (sk电讯)   ,,,,,,,skt.close ()   ,,,,,,,socket_list.remove (sk电讯)   时间=socket_list  []   #,负责监听“客户端连接进来“事件的函数   def 接受(袜子,面具):   康涅狄格州,,,,,addr =, sock.accept ()   ,,,#,使用socket_list保存代表客户端的插座   ,,,socket_list.append(康涅狄格州)   ,,,conn.setblocking(假)   ,,,#,使用选取为康涅狄格州的EVENT_READ事件注册读监听函数   ,,,sel.register(康涅狄格州,selectors.EVENT_READ,,读),,,,#②   时间=sock  socket.socket ()   sock.bind ((& # 39; 192.168.1.88& # 39;,, 30000))   sock.listen ()   #,设置该套接字是非阻塞的   sock.setblocking(假)   #,使用选取为袜子的EVENT_READ事件注册接受监听函数   sel.register(袜子,selectors.EVENT_READ,接受),,,,#①   #,采用死循环不断提取选取的事件   while 真正的:   ,,,events =, sel.select ()   ,,,for 关键,,mask 拷贝事件:   ,,,,,,,#,关键的数据属性获取为该事件注册的监听函数   ,,,,,,,callback =key.data   ,,,,,,,#,调用监听函数,,关键的fileobj属性获取被监听的套接字对象   ,,,,,,,回调(key.fileobj,面具)

上面程序中定义了两个监听器函数接受读()和(),其中接受()函数作为“有客户端连接进来“事件的监听函数,主程序中的①号代码负责为套接字的选择器。EVENT_READ事件注册该函数;阅读()函数则作为“有数据可读”事件的监听函数,如接受()函数中的②号代码所示。

通过上面这种方式,程序避免了采用死循环不断地调用插座的接受()方法来接受客户端连接,也避免了采用死循环不断地调用插座的recv()方法来接收数据.socket的接受(),recv()方法调用都是写在事件监听函数中的,只有当事件(如“有客户端连接进来“事件,“有数据可读”事件)发生时,接受()和recv()方法才会被调用,这样就避免了阻塞式编程。

为了不断地提取选择器中的事件,程序最后使用一个死循环不断地调用选择器的选择()方法”监测”事件,每当监测到相应的事件之后,程序就会调用对应的事件监听函数。

Python利用选择器模块实现非阻塞式编程