select及触发方式和监听多连接

'''IO多路复用'''
# select及触发方式和监听多连接
from socket import *
import select

sk = socket(AF_INET, SOCK_STREAM)
sk.bind(('127.0.0.1', 8080))
sk.listen(5)
inp = [sk] # 有新的连接,那么sk会发生变化

while True:
    # conn, addr = sk.accept()之前是这种方式监听连接,sk(socket对象)是一种文件描述符,有连接后会发生变化,再调用accept()方法
    r, w, e = select.select(inp, [], [], 6) # input输入列表---监听sk的变化,sk无变化r为空那么监听会处于阻塞的状态;output输出列表;errorput错误列表;6代表监听时长(单位秒)
    for i in r:
        if i == sk:
            conn, addr = i.accept()
            # conn也是一个socket对象
            inp.append(conn)
            # 把conn也添加进输入列表进行监听,如果客户端有数据发送那么conn也会有变化,如果没有数据发送则不会变化;此时也实现了并发,只要任意一个客户端发送了数据,那么对应的conn就会有变化select能够监听到
            print(conn, addr)
        else:
            try:
                data = i.recv(1024)
                print('客户端发送的消息:', data.decode('utf-8'))
                i.sendall(data.upper())
            except Exception:
                inp.remove(i)
    # sk类似一张表,是属于水平触发(accept方法没调用,那么一直处于一种频率),有连接了相当于有数据发生了变化,
    # 然后调用accept()方法类似于表与表之间的信息传递(sk电频再次发生变化),数据从内核态读取到用户态的过程,读取完毕sk又是为空

'''
触发方式:
    1.水平触发:也就是只有高电频(1)或低电频(0)时才触发通知,只要在这两种状态就能得到通知,上面提到的只要有数据可读(描述符就绪)那么水平触发的epoll就立即返回
    2.边缘触发:只有电频发生变化(高电频到低电频,或者低电频到高电频)的时候才触发通知,上面提到即使有数据可读,但是没有新的IO活动到来,epoll也不会立即返回

IO多路复用优势:同时可以监听多个连接
IO多路复用3种方法:
    select(全系统适用,windows/linux等,最多监听1024个),每一个监听对象发生变化了都需要进行一遍轮询,因为不知道具体是哪一个对象发生了变化,耗费时间
    poll(windows没有,linux有,相比于select最大连接数提高了)
    epoll(三种方法中最好的一个,windows没有,linux有),无论是哪一个监听对象发生了变化都需要自报信息,这样去取数据时就不需再进行轮询浪费多余的时间了
'''
from socket import *
import time

cl = socket(AF_INET, SOCK_STREAM)
cl.connect(('127.0.0.1', 8080))
while True:
    # msg = input('输入:').strip()
    cl.sendall('客户端one'.encode('utf-8'))
    data = cl.recv(1024)
    print('服务端回复:',data.decode('utf-8'))
    # cl.close()
    time.sleep(3)
while True: print('studying...')
原文地址:https://www.cnblogs.com/xuewei95/p/14883831.html