select模块学习

本文介绍了Python中的select和selectors模块,用于实现高效的并发网络通信。详细讲解了select的工作原理及其在Linux平台上的限制,并提供了使用select和selectors模块的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

select模块学习

一、select模块

select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。
select目前几乎在所有的平台上支持
 

select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。
 

另外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。

#sever端
import socket,select
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen(5)
inp = [sk,]
while 1:
    r,w,e = select.select(inp,[],[],5)   # timeout超时设置
    print('r:',r)
    print('w:',w)
    print('e:',e)

    for obj in r:                    #sk或是conn有变化时进入循环
        if obj == sk:                 #新的connect会触发sk,没有新connect则不会触发
            conn,add = obj.accept()
            print('conn:',conn)
            inp.append(conn)            #将conn加入到监听列表
        else:                          #conn变化
            data_byte = obj.recv(1024)
            print(str(data_byte,'utf8'))
            res = input('回答%s号客户:>>>'%inp.index(obj))
            obj.sendall(bytes(res,'utf8'))

    print('>>',r)                     #r中活动的对象
#client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

while 1:
    inp = input(">>>")
    sk.sendall(bytes(inp,'utf8'))
    data = sk.recv(1024)
    print(str(data,'utf8'))

二、selectors

#sever
import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock,mask):
    conn,addr = sock.accept()
    print('accepted',conn,'from',addr)
    conn.setblocking(False)
    sel.register(conn,selectors.EVENT_READ,read)

def read(conn,mask):
    try:
        data = conn.recv(1024)
        if not data:
            raise Exception
        print('echoing',str(data,'utf8'),'to',conn)
        data1 = input('回复:')
        conn.send(bytes(data1,'utf8'))
    except Exception as e:
        print('closing',conn)
        sel.unregister(conn)
        conn.close()

sock = socket.socket()
sock.bind(('localhost',8080))
sock.listen(100)
sock.setblocking(False)

sel.register(sock,selectors.EVENT_READ,accept)
print('server......')

while 1:
    events = sel.select()      #[sock,conn,conn2]
    for key,mask in events:
        print('key',key)
        print('mask',mask)
        callback = key.data     #accept/read
        print('c')
        callback (key.fileobj, mask)    #


#client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

while 1:
    inp = input(">>>")
    sk.sendall(bytes(inp,'utf8'))
    data = sk.recv(1024)
    print(str(data,'utf8'))        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值