'''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)