python socket select IO多路复用 sockeserver简单使用
1.IO多路复用 select(有最大连接数限制),pool(没有最大连接数限制),epool(异步)
服务器端:
import socket import select sscok = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sscok.bind(('127.0.0.1',8888)) sscok.listen(5) inputs = [sscok,] while True: r_list,w_list,e_list = select.select(inputs,[],[],1) print('正在监听的%s个对象'%len(inputs)) print(r_list) for sk in r_list: if sk == sscok: conn,addr = sk.accept() inputs.append(conn) else: try: data = sk.recv(1024) sk.sendall(data) except Exception as e: inputs.remove(sk) sscok.close()
客户端:
import socket csock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) csock.connect(('127.0.0.1',8888,)) while True: data = input('请输入要输入的内容') csock.sendall(bytes(data,encoding='utf-8')) data = csock.recv(1024) print(str(data,encoding='utf-8')) csock.close()
读写分离,实现伪并发 :服务器端如下,客户端不变
#!/usr/bin/env python # --*-- encoding:utf-8 --*-- import socket import select # 这种方式:同时接听了多个电话,哪个电话发出了声音,就回复哪个电话 sscok = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sscok.bind(('127.0.0.1',8888)) sscok.listen(5) #用于消息的读 inputs = [sscok,] #用于消息的写 outputs = [] #用于读写分离是,消息的存放 dicta = {} while True: # 如果inputs里面发生变化时,会添加到r_list, outputs所有元素添加到w_list,出错的放在e_list r_list,w_list,e_list = select.select(inputs,outputs,inputs,1) #当有客户端连接是对象+1 print('正在监听的%s个对象'%len(inputs)) #当inputs变化时,r_list存放变化的那一个元素 print(r_list) for sk in r_list: #消息的读 if sk == sscok: #客户端的连接,变化的是sscok conn,addr = sk.accept() #接受客户的连接 inputs.append(conn) #将连接返回的socket对象添加到监听列表中 dicta[conn] = [] #在字典中添加一个conn:空列表 else: #客户端发送过消息,变化的conn,此时conn已经添加到监听列表 try: data = sk.recv(1024) #接收消息 dicta[sk].append(str(data,encoding='utf-8')) #更新字典 outputs.append(sk) #添加到outputs,方便后面的写 # sk.sendall(data) except Exception as e: inputs.remove(sk) #客户端中断,将对应的连接删除 for sk in w_list: #消息的写 recv_str = dicta[sk][0] #读取字典 del dicta[sk][0] #删除字典的元素 sk.sendall(bytes('自动回复:'+recv_str,encoding='utf-8')) # 向outputs里面元素发送消息 outputs.remove(sk) #发送完消息,删除outputs元素 for sk in e_list: inputs.remove(sk) #连接异常,则删除这个连接 sscok.close()
2.上面实现的是一种伪并发的情况,真正要实现多线程并发,需要利用socketserver模块
#!/usr/bin/env python # -*- coding:utf-8 -*- import SocketServer class MyServer(SocketServer.BaseRequestHandler): def handle(self): //some method.... if __name__='__main__': server = SocketServer.ThreadingTCPServer(('127.0.0.1,9999'),MyServer) server.serve_forever()
- 自定义一个类,继承chenSocketServer.BaseRequestHandler,并重写handle方法
- 通过访问self.request ,就可以访问到连接过来的socket对象

浙公网安备 33010602011771号