select模块(I/O多路复用)

2019-07-24 16:48:46 浏览数 (1)

0709自我总结

select模块

一.介绍

Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统)

二.select方法

r_list,w_list,e_list = select.select(rlist, wlist, xlist, [timeout])

三个参数

  • rlist
    • wait until ready for reading(等待,直到准备阅读)
    • 在tcp协议中accept与recv都存在一个等待的过程他们要等数据过来才会执行消息发来后他会进入一个可读状态
  • wlist
    • wait until ready for writing(等待,直到准备写)
    • 在tcp协议send不存在一个等待的过程,他会直接把信息丢到缓存,然后这时候会进入可写状态
  • xlist
    • wait for an “exceptional condition”(等待,有异常情况)
  • timeout
    • 当超时时间为空,则select会一直阻塞,直到监听的句柄发生变化
    • 当超时时间 = n(正整数)时,那么如果监听的句柄均无任何变化,则select会阻塞n秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

示例:

服务端

代码语言:javascript复制
import socket
import time
import select
s = socket.socket()
s.bind(("127.0.0.1",1688))
# 设置为非阻塞 模型
s.setblocking(True) #在多路复用中  阻塞与非阻塞没有区别 因为select会阻塞直到有数据到达为止
s.listen(5)
# 待检测是否可读的列表
r_list = [s]
# 待检测是否可写的列表
w_list = []
# 待发送的数据
msgs = {}
print("开始检测了")
while True:
    read_ables, write_ables, _= select.select(r_list,w_list,[])
    print("检测出结果了!")
    # print(read_ables,"可以收数据了")
    # print(write_ables,"可以发数据了")
    # 处理可读 也就是接收数据的
    for obj in read_ables: # 拿出所有可以读数据的socket
        #有可能是服务器 有可能是客户端
        if s == obj: # 服务器
            print("来了一个客户端 要连接")
            client,addr = s.accept()
            r_list.append(client)  # 新的客户端也交给select检测了
        else:# 如果是客户端则执行recv 接收数据
            print("客户端发来一个数据")
            data = obj.recv(1024)
            print("有个客户端说:",data)
            # 将要发送数据的socket加入到列表中让select检测
            w_list.append(obj)
            # 将要发送的数据已经socket对象丢到容器中
            if obj in msgs:  # 由于容器是一个列表 所以需要先判断是否已经存在了列表
                msgs[obj].append(data)
            else:
                msgs[obj] = [data]
    # 处理可写的 也就是send发送数据
    for obj in write_ables:
        msg_list = msgs.get(obj)
        if msg_list:
            # 遍历发送所有数据
            for m in msg_list:
                obj.send(m.upper())
            # 数据从容器中删除
            msgs.pop(obj)

        # 将这个socket从w_list中删除
        w_list.remove(obj)

客户端

代码语言:javascript复制
import socket
c = socket.socket()
c.connect(("127.0.0.1",1688))

while True:
    msg = input("").strip()
    if not msg:continue
    c.send(msg.encode("utf-8"))
    print(c.recv(1024).decode('utf-8'))

后续几种方法以后总结补充

0 人点赞