一. 简介
socketserver在内部是由I/O多路复用,多线程和多进程,实现了并发通信。IO多路复用的系统消耗很小。
IO多路复用底层就是监听socket对象内部是否有变化,是否在收发消息,Python中select模块提供了select poll epoll 三种方式来实现IO多路复用,支持不同的操作系统。
windows : 提供select
Mac : 提供select
Linux : 提供select, poll, epoll
(1)select简介:
select 默认会将每一个变化的socket加入一个他自己维护的列表中,但是并不会明确是哪一个socket,它内部其实是通过一个for循环遍历整个列表,当列表中的socket很多的时候,for循环就会浪费资源。select默认可以监听1024个链接,它是由linux在同文件中定义的,可修改。select不是安全的线程,如果你把一个socket加入到select中,突然另外一个线程关闭了这个socket,那么接下来select的行为是随机的。
(2)poll简介:
poll修复了select的一些问题,例如去掉了1024个链接限制,想要监听多少都可以,poll不在修改传入的数组,但是poll依然不是线程安全的。
(3)epoll简介:
epoll不仅会告诉你socket组里面的数据,还会告诉你具体哪个socket有数据,无需自己寻找。而且epoll终于是线程安全的了。然而epoll局限于
Linux操作系统。
二 . 应用
select 方法
句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)<br> 参数: 可接受四个参数(前三个必须) 返回值:三个列表 select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。 1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中 2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中 3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中 4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化 当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。
(1)监听客户端连接
import socket import select sk = socket.socket() sk.bind(("127.0.0.1", 9999,)) sk.listen(5) while True: rlist, w, e = select.select([sk, ], [], [], 5) # 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为[sk] # 监听conn对象,如果conn发生变化,表示客户端有消息发送过来了,此时rlist的值为[客户端] print(rlist) for r in rlist: print(r) conn, address = r.accept() conn.sendall(bytes("hello", encoding="utf-8"))