Python---select模块的使用

select vs epoll

  • 连接数量不高但是很活跃select
  • 连接数量搞但是不活跃 epoll

select模块的使用:

select会监听socket或者文件描述符的I/O状态变化,并返回变化的socket或者文件描述符对象

select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)

这是Python select方法的原型,接收4个参数

  1. rlist:list类型,监听其中的socket或者文件描述符是否变为可读状态,返回那些可读的socket或者文件描述符组成的list
  2. wlist:list类型,监听其中的socket或者文件描述符是否变为可写状态,返回那些可写的socket或者文件描述符组成的list
  3. xlist:list类型,监听其中的socket或者文件描述符是否出错,返回那些出错的socket或者文件描述符组成的list
  4. timeout:设置select的超时时间,设置为None代表永远不会超时,即阻塞。

注意:

  1. Python的select方法在Windows和Linux环境下的表现是不一样的,Windows下它只支持socket对象,不支持文件描述符(file descriptions),而Linux两者都支持。

  2. 我们可以通过打印来查看select模块提供的作用,返回的rlist,wlist只会返回有改变的监听对象,如果没有改变的函数,那么整个程序会阻塞住

  3. 如果我们想要加入新的连接,那么我们只需要把连接对象放进rlist即可,当有数据过来的时候,那么连接就会发生改变(文件描述符),select函数就会帮我们监听到

  4. 如果我们想发送数据,那么我们可以把conn加入到wlist,因为发送数据需要我们去输出流数据,然后等待select把wlist里面的消息取出来,我们就可以发送数据了


# python select io多路复用测试代码
# 1. 简单的使用select来进行客户端多连接

import select
import socket
import time

# select 把socket放入 select中,然后每当有一个连接过来,把连接conn放入select模型里面去

port = 19834
ip = "127.0.0.1"

ss = socket.socket()
ss.bind((ip, port))
ss.listen(10)

readable_list = [ss]


while 1:
    # print('listen again')
    rlist, wlist, xlist = select.select(readable_list, [], [],5)
    # 如果遍历出来的
    print('listen to the readable sockets',rlist)
    print('length of the readable sockets',len(rlist))
    print('length of the total sockets', len(readable_list))
    for i in rlist:
        if i is ss:
            #如果ss准备就绪,那么说明ss就可以接受连接了,当ss接受到连接
            #那么把连接返回readlist
            conn,addr = i.accept()
            readable_list.append(conn)

注意点 每次我们都需要把send的conn给移除出wlist才行,不然每次conn都会准备好写入,无限的循环

1. 简单的使用select来进行客户端多连接:

import select
import socket
import time

#select 把socket放入 select中,然后每当有一个连接过来,把连接conn放入select模型里面去
port = 19860
ip = "127.0.0.1"
ss = socket.socket()
ss.bind((ip, port))
ss.listen(10)
read_list = [ss]
write_list = []
msg_list = dict()
while 1:
    # print('listen again')
    rlist, wlist, xlist = select.select(read_list, write_list, [], 5)
    for i in rlist:
        if i is ss:
            # 如果ss准备就绪,那么说明ss就可以接受连接了,当ss接受到连接
            # 那么把连接返回readlist
            conn, addr = i.accept()
            read_list.append(conn)
        # 如果不是socket对象,那么就是conn连接对象了,如果是conn连接对象,那么就代表有
        # 读入数据的变化,对应recv方法
        else:
            try:
                data = i.recv(1024)
                # 如果接受不到数据了 则说明连接已经关闭了
                if not data:
                    print('connecting close')
                    read_list.remove(i)
                    break
                # 我们去发送数据,但是我们要把conn准备好了再去发送
                # 所以首先把数据存在一个dict中msg_list,然后再等他准备好的时候
                # 再去发送
                msg_list[i] = [data]
                if i not in write_list:
                    write_list.append(i)
            except Exception:
                read_list.remove(i)

    for j in wlist:
        # 把对应各自的消息取出来
        msg = msg_list[j].pop()
        try:
            j.send(msg)
            # 回复完成后,一定要将outputs中该socket对象移除
            write_list.remove(j)
        except Exception:
            # 如果报错就所以连接或者已经断开了,那么我们就把他移出出去
            write_list.remove(j)
发布了38 篇原创文章 · 获赞 11 · 访问量 9250
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览