服务端的代码

import socket
import queue
import select
ip_bind = ("127.0.0.1",9000) message_queue = {}
#保存客户端发送过来的信息,将消息放入到队列中 input_list = [] output_list = [] if __name__ == '__main__':
server = socket.socket()
server.bind(ip_bind)
server.listen(10)
server.setblocking(False)
#设置socket服务端为非阻塞的 input_list.append(server)
#初始化将服务端加入到监听列表中 while True:
print("waiting for new connection")
stdinput,stdoutput,stderr = select.select(input_list,output_list,input_list,2)
#开始select监听,对input_list中的服务端server进行监听 for obj in stdinput:
#判断是否有客户端连接进来,当有客户端连接进来时select将触发,就会进入循环 if obj == server: #代表一个新的连接进来
#判断当前触发的是不是服务端的对象,当触发的对象是服务端的对象时候,说明
#有新的客户端连接进来了 conn,addr = server.accept()
print("Client {0} is connected".format(addr))
conn.setblocking(False)
#把这个新连接的实例设置为非阻塞 #这个时候我们不能立即接受数据,因为在select中,是单线程的,如果这里直接开始接受数据,那么其他的客户端就无法连接进来了,所以只能
#先把这个链接存起来,放到一个input_list中,为什么放到input_list中呢,因为我们想监控这个链接,如果这个客户端有消息过来,那么select
#就会触发,如果没有数据返回,则select就不会被触发 input_list.append(conn)
#将和这个客户端的连接的服务端的实例也加入到监听列表中,当客户端发送消息的
#时候,select就会被触发 message_queue[conn] = queue.Queue()
#为这个连接的客户端单独创建一个独一无二的消息队列,用来保存客户端发送的消息。 else: #代表一个有数据的链接进来了,这个时候我就可以开始收数据了 #由于客户端连接进来时服务端接受客户端的连接请求,将这个客户端的服务端的
#也加入到监听列表中,这个客户端如果发送消息,则会触发select
try:
recv_data = obj.recv(1024)
if recv_data:
#客户端未断开
print("received {0} from client {1}".format(str(recv_data,encoding="utf-8"),addr)) #将收到的信息放入该客户端的队列中
message_queue[obj].put(recv_data) #此时也不能直接给客户端返回数据,因为一旦返回数据,就又可能造成阻塞,所有将回复操作放到output列表中,让select监听
if obj not in output_list:
output_list.append(obj) except ConnectionResetError:
input_list.remove(obj)
del message_queue[obj]
print("client {0} is disconnected".format(addr)) for sendobj in stdoutput: #这里处理的是返回的消息,output_list是我们自己维护的,我们自己往里面放数据
try:
if not message_queue[sendobj].empty():
#如果消息队列中有消息,从消息队列中获取要发送的消息
send_data = message_queue[sendobj].get()
#从该客户端对象的消息队列中获取消息
sendobj.sendall(send_data)
else:
output_list.remove(sendobj)
#将监听移除等待瞎猜疑客户端发送消息
except ConnectionResetError:
#客户端连接断开
del message_queue[sendobj]
output_list.remove(sendobj)
print("Client {0} disconnected".format(addr)) for obj in stderr: #如果出错的处理
# print()
input_list.remove(obj)
if obj in output_list:
output_list.remove(obj)
obj.close()
del message_queue[obj]

  

05-11 13:48