栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python与select,epool使用

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python与select,epool使用

select 来自于百度的一段解释:
	Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。
可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。
本人理解的解释:
第一阶段  在普通的socket编写的时候呢,是阻塞模式,也就是监听的时候进行阻塞监听。使用程序本身来监听有多少用户过来,检测用户是否有信息到达等等

第二阶段 使用多线程来处理,主线程负责创建socket进行实例化,线程二负责阻塞链接,一旦有链接就将此次链接的文件描述符存储起来,调用的时候获取到 然后send信息 线程三负责阻塞监听是否有信息到达,并做相应的处理
上面一些操作属于IO操作 
下面的就利用到一些名词了...  IO多路复用(我用白话讲吧,IO多路复用就是利用自己程序的IO同时再用系统自己的IO,俗称IO多路复用,如果我解释的有错欢迎指点,我及时修改)

第三阶段 使用IO多路复用,根据我上面的解释就是利用系统去检测当前文件描述符(Linux一切皆文件)(白话就是socket当前对象),将这个文件描述符交给操作系统而不是你自己的程序进行监听,让程序去处理,如果检测的能读或者能写,系统来通知你(程序)来读或者写。

第四阶段 使用信号量(本人暂未使用)
注释:(我喜欢用白话去说,不喜欢用专业的修饰词,因为感觉说出口模棱两可,具体理解的对或者不对也不知道,专业的修饰词说出口好像是你会了,实际呢?谁知道?当然白话自己解释也会出现理解问题,如果出错请大家即使指正) 专业解释

我觉得解释的还不错,请点击查看

自己代码实现
引用包
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE
实例化对象
epoll_obj = DefaultSelector()
实例化SOCKET对象
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 再次对socket对象进行设置,这个是端口复用
SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 监听的端口
self.SOCKET.bind(("0.0.0.0" 9999))
# 最大承受量(单次)
 SOCKET.listen(100)
 # 是否阻塞模式
 SOCKET.setblocking(False)
 # 查看文件描述符  ()
 log.info(str(SOCKET))
 # 启动个线程whlie True 去检测用户链接
 thread = Thread(target=initial_accept_message, kwargs={"socket": self.SOCKET})
 thread.setDaemon(True)
 thread.setName("辅助接受用户线程")
 thread.start()
  # 启动个线程whlie True 去轮训select回调函数
 thread = Thread(target=self.loop)
 thread.setDaemon(True)
 thread.setName("辅助管理线程")
 thread.start()
检测用户链接
def initial_accept_message(self, *args, **kwargs):
    #获取到socket对象
    s = kwargs.get("socket")
    while True:
        # 阻塞循环接受监听
        conn, address = s.accept()
        #  打印监听到的文件描述
        log.info('accepted%s,from%s,cnn%s' % (str(conn), str(address), str(conn)))
        #  是否阻塞模式
        conn.setblocking(False)
        # 开始注册回调函数  
        self.epoll_obj.register(conn, EVENT_WRITE,link_write_bank)
当可写的时候
def link_write_bank(self, sock, mask):
	# 发送信息
	sock.send(bytes.fromhex("我爱中华"))
	# 取消当前socket(并不是刚刚实例化的宏,这个socket是刚刚链接进来的那个对象)
    self.epoll_obj.unregister(sock)
    # 再次注册可读
    self.epoll_obj.register(sock, EVENT_READ, self.accept_bankId_host)
可读
    def accept_host(self, sock, mask):
    	# 通过对象读取信息
        res = sock.recv(1024)
		# 对方地址  __str__
        conn = sock.accept
        。。。。。后续操作
辅助管理线程
    def loop(self):
    	# 死循环
        while True:
        	# 实例化当前的epool_obj中的阻塞监听事件对象
            events = self.epoll_obj.select()
            # 循环监听对象
            for key, mask in events:
            	# 拿取回调函数
                callback = key.data
                # 启动回调函数,输入当前的socket对象
                callback(key.fileobj, mask)
最后的解释 DefaultSelector
Windows使用自动调取select  Linux 调取epool   下周解释epool
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/488530.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号