2018.4.1学习笔记(I/O多路复用,利用到select模块)
2018-04-01 22:30 冒牌权限 阅读(102) 评论(0) 收藏 举报利用select模块来实现I/O多路复用(I/O多路复用其实本身是由系统底层来实现的,windows只支持select,由系统去循环监测,效率较低,poll优化了select,不过还是循环,效率较低,linux支持epoll,由文件描述符主动告知epoll,异步,效率高)
#!/usr/bin/env python # -*- coding:utf-8 -*- #####服务端##### import socket,select sk1 = socket.socket() sk1.bind(('127.0.0.1',10001)) sk1.listen() sk2 = socket.socket() sk2.bind(('127.0.0.1',10002)) sk2.listen() sk3 = socket.socket() sk3.bind(('127.0.0.1',10003)) sk3.listen() inputs = [sk1,sk2,sk3] while True: r_list,w_list,e_list = select.select(inputs,[],inputs,1)#最后那个1代表每1秒监测一次 #r_list监测的变化的文件描述符,有值就表示该描述符有变化 #w_list监测所传过来的参数,传了什么就是什么 #e_list监测出错的文件描述符,有值就表示该描述符出错 for sk in r_list: conn,address = sk.accept() conn.sendall(bytes('老铁,你来啦',encoding='utf-8')) conn.close() for sk in e_list: inputs.remove(sk)#把出错的文件描述符去除
伪造多用户连接
#!/usr/bin/env python # -*- coding:utf-8 -*- #####服务端##### import socket,select sok = socket.socket() sok.bind(('127.0.0.1',10001)) sok.listen() inputs = [sok,] while True: r_list,w_list,e_list = select.select(inputs,[],inputs,1) for sk in r_list: if sk == sok: conn,address = sk.accept() inputs.append(conn)#把连接(即客户端的信息)加入列表,当客户端有发消息过来时就可以利用了 else: try: sk.recv(1024)#因为sk不等于sok,所以这时候sk就是上边那个conn了 sk.sendall(bytes('老铁,你来啦',encoding='utf-8')) except Exception as ex: inputs.remove(sk) #####客户端##### import socket obj = socket.socket() obj.connect(('localhost',10001))#要请求的服务器ip和端口 while True: inp = input('>>>') no_str = ['exit'] if inp in no_str: break obj.sendall(bytes(inp,encoding='utf-8')) ret = str(obj.recv(1024),encoding='utf-8') print(ret) obj.close()
读写分离式伪并发
#!/usr/bin/env python # -*- coding:utf-8 -*- #####服务端##### import socket,select sok = socket.socket() sok.bind(('127.0.0.1',10001)) sok.listen() sok_inp = [sok,]#r_list用 sok_li = []#w_list用 sok_dict = {}#消息记录用 while True: r_list,w_list,e_list = select.select(sok_inp,sok_li,sok_inp,1) for sk in r_list: if sk == sok: conn,address = sk.accept()#等待连接 sok_inp.append(conn)#把连接添加进sok_inp sok_dict[conn] = []#消息记录里创建连接与值的对应关系 else: try: value = str(sk.recv(1024),encoding='utf-8')#一但收到对端发来消息,则接收并转换为字符串 except Exception as ex: sok_inp.remove(sk)#如果对端断开连接或出错,则删除这个连接 else: sok_li.append(sk)#把发消息的连接添加到sok_li列表 sok_dict[sk].append(value)#把消息添加到消息记录 for conn in w_list: ret = sok_dict[conn][(len(sok_dict[conn]) - 1)]#获取发消息的那条连接的最后一条消息记录 sk.sendall(bytes(ret + '老铁,你来啦', encoding='utf-8')) sok_li.remove(conn)#删除发消息的连接,这里可以看出sok_li里始终只有一条连接 #####客户端##### import socket obj = socket.socket() obj.connect(('localhost',10001))#要请求的服务器ip和端口 while True: inp = input('>>>') no_str = ['exit'] if inp in no_str: break obj.sendall(bytes(inp,encoding='utf-8')) ret = str(obj.recv(1024),encoding='utf-8') print(ret) obj.close()
浙公网安备 33010602011771号