python的select服务端的代码和客户端的代码详解编程语言

服务端的代码

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] 

  

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/20869.html

(0)
上一篇 2021年7月19日 23:51
下一篇 2021年7月19日 23:51

相关推荐

发表回复

登录后才能评论