Client:
#!/usr/bin/env python # -*- coding: utf-8 -*- import socket client = socket.socket() client.connect(('127.0.0.1',9999)) # client.close() while True: data = client.recv(1024) print(data) input('>>>')
Server:
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' IO多路复用实现伪并发 IO多路复用:select、poll、epoll 用来监听socket对象的内部是否变化了(变化是指:socket连接或收发消息) 服务器端的socket对象发生变化------->表示有新连接来了 服务器端有2个对象:server发生变化---->有新连接来了 server接收到新连接,生成conn:conn发生变化----->要收发消息了 ''' #服务端代码 import socket import select server = socket.socket() server.bind(('127.0.0.1',9999)) server.listen(5) #conn,address = server.accept() # server1 = socket.socket() # server1.bind(('127.0.0.1',9998)) # server1.listen(5) while True: # 使用IO多路复用 # 监听服务端的socket对象(server、server1等)的变化(可监听多个对象),对象发生变化时(有新连接来了), # 就将发生变化的对象写入r中(多个对象发生变化,就将变化的对象都写入r中---r是一个列表) #timeout:超时时间,监听等待1秒,如果没有变化就进行下一次循环 #r是一个获取到新连接的对象列表 r,w,e = select.select([server,],[],[],1) print('r:',r) #for循环能执行的前提是server发生变化(有客户端连接了,没有客户端连接r就是空的,即对象没发生变化) for s in r: print('s',s) #conn是客户端连接对象,这里没有进行监听就直接进行下一次循环了 conn,addr = s.accept() conn.sendall(bytes('hello',encoding='utf-8'))
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' IO多路复用实现伪并发 IO多路复用:select、poll、epoll 用来监听socket对象的内部是否变化了(变化是指:socket连接或收发消息) 服务器端的socket对象发生变化------->表示有新连接来了 服务器端有2个对象:server发生变化---->有新连接来了 server接收到新连接,生成conn:conn发生变化----->要收发消息了 ''' #服务端代码 import socket import select server = socket.socket() server.bind(('127.0.0.1',9999)) server.listen(5) while True: inp = [server,] # 使用IO多路复用,监听inp中的对象 r,w,e = select.select(inp,[],[],1) print('r:',r) #对象发生变化时,对象有可能是server变化(新连接)、也有可能是已有的客户端对象进行收发消息 #r = [server,] #r = [conn,] for s in r: print('s',s) if s == server: #表示新客户端连接 #conn是客户端连接对象,要想后续继续监听该对象来进行和客户端的通信(收发消息) #可以把该对象也加入select多路复用,进行循环监听 conn,addr = s.accept() inp.append(conn) conn.sendall(bytes('hello', encoding='utf-8')) else: #客户端连接进行收发消息 conn = s try: recv_data = conn.recv(1024) if not recv_data: raise Exception('接收的数据为空,断开连接') except Exception as e: #客户端断开连接,就将该客户端对象从inp中移除 inp.remove(s)
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' IO多路复用实现伪并发 select:支持跨平台、使用for循环来实现(效率不高)、监听个数有限制(最大监听1024个) poll:使用for循环实现、没有监听个数限制 epoll:实现方法不同以上两种,效率更高 ''' #服务端代码 import socket import select server = socket.socket() server.bind(('127.0.0.1',9999)) server.listen(5) while True: inp = [server,] #存放所有监听的对象 out = [] #存放所有给服务端发过消息的客户端对象 message = {} #存放客户端给服务器发送的消息。例:conn:[消息1,消息2] # 使用IO多路复用,监听inp中的对象 r,w,e = select.select(inp,out,[],1) #r:发生变化的对象 w:发过消息的客户端对象 print('r:',r) #对象发生变化时,对象有可能是server变化(新连接)、也有可能是已有的客户端对象进行收发消息 print('w:',w) #客户端给服务端发送消息时,先不做处理,而是将该客户端添加到out中,等到循环时服务端再统一进行处理(读写分离) #r = [server,] #r = [conn,] for s in r: print('s',s) if s == server: #表示新客户端连接 #conn是客户端连接对象,要想后续继续监听该对象来进行和客户端的通信(收发消息) #可以把该对象也加入select多路复用,进行循环监听 conn,addr = s.accept() inp.append(conn) #将客户端对象添加到inp监听列表中 message[conn] = [] #在message中创建一个key:value用来存放客户信息(conn:[]) conn.sendall(bytes('hello', encoding='utf-8')) else: #客户端连接进行收发消息 conn = s try: recv_data = conn.recv(1024) if not recv_data: #接收数据为空 raise Exception('接收的数据为空,断开连接') else: #接收数据正常 out.append(conn) #将该客户端对象加入out列表中 message[conn].append(recv_data) except Exception as e: #客户端断开连接,就将该客户端对象从inp中移除,并将该对象所有的消息也一并移除 inp.remove(s) del message[s] #循环w(w对应的是out列表),这里专门对发过消息的客户端进行回复 for s in w: recv_data = message[s].pop() s.sendall(bytes('response:%s'%recv_data,encoding='utf-8')) out.remove(s) #恢复完毕,将该客户端对象从out中移除
关注我的公众号,不定期推送资讯
本文来自博客园,作者:链条君,转载请注明原文链接:https://www.cnblogs.com/MacoLee/articles/6125596.html