美文网首页
04协程番外:IO多路复用之select服务器案例第一版

04协程番外:IO多路复用之select服务器案例第一版

作者: 依依东望_220b | 来源:发表于2019-01-25 18:25 被阅读0次

    Python的select使用关键点就select模块的select函数
    import select
    readables,writeables,exceptions=select.select(readable_list,writeable_list,exception_list,time_out) #1
    每执行 1 这句话话,
    情况一:
    time_out为空的情况下,select会监听:
    readable_list中的资源是否可读,将读就绪的资源返回到readables
    writeable_list中的资源是否可写,将写就绪的资源返回到writeables
    exception_list中的资源是否发生异常,将发生异常的资源放入exceptions
    当所有资源都没有就绪的时候,select.select会阻塞当前线程,直到有某个资源就绪,然后返回
    情况二:
    time_out不为空的情况下,select会监听:
    readable_list中的资源是否可读,将读就绪的资源返回到readables
    writeable_list中的资源是否可写,将写就绪的资源返回到writeables
    exception_list中的资源是否发生异常,将发生异常的资源放入exceptions
    当所有资源都没有就绪的时候,select.select会阻塞当前线程,直到在time_out时间内有某个资源就绪,然后返回;如果在timeout时间内没有资源就绪,那就返回三个空列表,也就是readables=writerables=exceptisons=[]

    import select
    import socket
    import time
    SERVER_HOST=('127.0.0.1',9999)
    
    class Select_Server_01:
        '''
        使用select和可读队列,可写队列实现服务器
        '''
        def __init__(self):
            #创建套接字
            self.server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            #绑定端口
            self.server_socket.bind(SERVER_HOST)
            #设置为监听套接字
            self.server_socket.listen(5)
            #可读就绪资源列表
            self.readable_list=[self.server_socket]
            #可写就绪资源列表
            self.writeable_list=[]
            '''
            存储客户端socket传递过来的参数
            存储结构如下
            键为:客户端socket对象,值为socket对象传入的值
            '''
            self.client_socket_args={}
    
        def handle_request(self,request_args):
            #根据传入参数返回对应的参数
            return "{}时刻,经过不负责任的socket处理过的数据:{}".format(time.time(),request_args)
    
        '''
        服务器运行核心,通过while循环 
        '''
        def run(self):
            """
            主循环,不断循环处理可读与可写队列
            :return:
            """
            while True:
                #select检查并返回可读与可写列表中那些就绪的socket
                readables,writerables,exceptions=select.select(self.readable_list,self.writeable_list,[])
    
                #处理每个可读的socket
                for readable_item in readables:
                    if readable_item==self.server_socket: #如果可读就绪的是服务器socket,则表示有新的客户端接入
                        client_socket,client_socket_address=readable_item.accept()
                        #将新的客户端socket存入可读列表
                        self.readable_list.append(client_socket)
                        print('接收到新socket:{}'.format(client_socket))
                    else:   #除了服务器socket就是客户端socket可读了,我们这里接收一下客户端socket数据(这里是普通参数)
                        recv_data=readable_item.recv(1024).decode('utf-8')  #这是一个堵塞操作,客户端最好不要一次发送太多的数据
                        if recv_data=='':
                            #如果客户端发送空字符串,表示自己要关闭,所以我们要清除这个客户端
                            #先关闭掉它
                            try:
                                readable_item.close()
                            except:
                                pass
                            #从客户端请求参数列表中清除
                            if readable_item in self.client_socket_args:
                                del self.client_socket_args[readable_item]
                            #从可读队列中清除
                            if readable_item in self.readable_list:
                                self.readable_list.remove(readable_item)
                            #从可写队列中清除
                            if readable_item in self.writeable_list:
                                self.writeable_list.remove(readable_item)
                            #从本轮的写就绪队列中删除(因为我们接下来会处理可写socket)
                            if readable_item in writerables:
                                writerables.remove(readable_item)
                            print('清除socket:{}'.format(readable_item))
                        elif recv_data!='CLOSE_SERVER_ZHOUYUQING':
                            #将请求参数存入客户端请求参数字典
                            self.client_socket_args[readable_item]=recv_data
                            #接下来我们要将客户端socket放入可写队列
                            if readable_item not in self.writeable_list:
                                self.writeable_list.append(readable_item)
                            print('处理socket:{}'.format(readable_item))
                        else: #客户端发过来是关闭指令
                            self.close()
                            return
                #处理每个可写的socket
                for writeable_item in writerables:
                    #获取这个socket对应传入参数
                    client_send_data=self.client_socket_args.get(writeable_item)
                    #向可写socket发送数据
                    print('当前关于该socket:{} 的传入参数是:{}'.format(writeable_item,client_send_data))
                    writeable_item.send(self.handle_request(client_send_data).encode('utf-8')) #阻塞操作
                    print('发送数据给:{}'.format(writeable_item))
                    #处理完这个可读socket后从可读队列中删除,知道它再次发送请求参数过来才会被添加到可读队列中
                    self.writeable_list.remove(writeable_item)
    
    
        '''
        关闭select_socket服务器
        '''
        def close(self):
            #关闭所有存在的socket
            for _socket in self.readable_list+self.writeable_list:
                try:
                    _socket.close()
                except:
                    pass
            print('服务器执行关闭所有操作')
    
    class Client_Socket_01:
        '''
        测试客户端socket
        '''
        def __init__(self):
            self.client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
        def run(self,info,num):
            self.client_socket.connect(SERVER_HOST)
            for _ in range(num):
                self.client_socket.send(info.encode('utf-8'))
                print('\n\n         {} 接收响应:{}\n\n'.format(info,self.client_socket.recv(1024).decode('utf-8')))
    
            #发送关闭动作(发送一个为空字符串)
            self.client_socket.send(''.encode('utf-8'))
            try:
                self.client_socket.close()
            except:
                pass
    
    import multiprocessing
    def main_01():
        #先启动服务器
        server_socket=Select_Server_01()
        multiprocessing.Process(target=server_socket.run).start()
    
        #启动测试客户端
        client_socket_01=Client_Socket_01()
        multiprocessing.Process(target=client_socket_01.run,args=('测试客户端1',1)).start()
        client_socket_02=Client_Socket_01()
        multiprocessing.Process(target=client_socket_02.run,args=('测试客户端2',3)).start()
        client_socket_03=Client_Socket_01()
        multiprocessing.Process(target=client_socket_03.run,args=('测试客户端3',6)).start()
        client_socket_04=Client_Socket_01()
        multiprocessing.Process(target=client_socket_04.run,args=('测试客户端4',9)).start()
    
        #创建一个客户端发送一个关闭指令给服务器
        time.sleep(30) #这句话很重要,你不要一上来就把服务器关了
        final_client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        final_client_socket.connect(SERVER_HOST)
        final_client_socket.send('CLOSE_SERVER_ZHOUYUQING'.encode('utf-8'))
        try:
            final_client_socket.close()
        except:
            pass
        print('-------------------------->>>>>>>>>>>>>>>>执行关闭服务器完毕')
    
    """
    执行:
        main_01()
    执行结果:
    
        接收到新socket:<socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34416)>
        接收到新socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
        处理socket:<socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34416)>
        当前关于该socket:<socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34416)> 的传入参数是:测试客户端1
        发送数据给:<socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34416)>
    
    
                 测试客户端1 接收响应:1548409232.0193949时刻,经过不负责任的socket处理过的数据:测试客户端1
    
    
        处理socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
        当前关于该socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)> 的传入参数是:测试客户端2
        发送数据给:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
    
    
                 测试客户端2 接收响应:1548409232.0195627时刻,经过不负责任的socket处理过的数据:测试客户端2
    
    
        处理socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
        当前关于该socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)> 的传入参数是:测试客户端2
        发送数据给:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
    
    
                 测试客户端2 接收响应:1548409232.0199127时刻,经过不负责任的socket处理过的数据:测试客户端2
    
    
        处理socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
        当前关于该socket:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)> 的传入参数是:测试客户端2
        发送数据给:<socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34418)>
        接收到新socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        处理socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        当前关于该socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)> 的传入参数是:测试客户端3
        发送数据给:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
    
    
                 测试客户端3 接收响应:1548409232.0201845时刻,经过不负责任的socket处理过的数据:测试客户端3
    
    
    
                 测试客户端2 接收响应:1548409232.020043时刻,经过不负责任的socket处理过的数据:测试客户端2
    
    
    
        处理socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        当前关于该socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)> 的传入参数是:测试客户端3
        发送数据给:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
    
    
                 测试客户端3 接收响应:1548409232.020338时刻,经过不负责任的socket处理过的数据:测试客户端3
    
    
        处理socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        当前关于该socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)> 的传入参数是:测试客户端3
        发送数据给:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        接收到新socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
    
    
                 测试客户端4 接收响应:1548409232.0205855时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
    
                 测试客户端3 接收响应:1548409232.020468时刻,经过不负责任的socket处理过的数据:测试客户端3
    
    
    
        处理socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)> 的传入参数是:测试客户端3
    
    
                 测试客户端3 接收响应:1548409232.0207088时刻,经过不负责任的socket处理过的数据:测试客户端3
    
    
        发送数据给:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        处理socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        当前关于该socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)> 的传入参数是:测试客户端3
    
    
                 测试客户端3 接收响应:1548409232.0208163时刻,经过不负责任的socket处理过的数据:测试客户端3
    
    
        发送数据给:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        处理socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
        当前关于该socket:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)> 的传入参数是:测试客户端3
    
    
                 测试客户端3 接收响应:1548409232.0208836时刻,经过不负责任的socket处理过的数据:测试客户端3
    
    
        发送数据给:<socket.socket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34422)>
    
    
                 测试客户端4 接收响应:1548409232.0207596时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
    
    
                 测试客户端4 接收响应:1548409232.0210006时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
    
    
                 测试客户端4 接收响应:1548409232.0211372时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
    
    
                 测试客户端4 接收响应:1548409232.021273时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
    
    
                 测试客户端4 接收响应:1548409232.0214124时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
    
    
                 测试客户端4 接收响应:1548409232.021508时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
    
    
                 测试客户端4 接收响应:1548409232.0216038时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        处理socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        当前关于该socket:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)> 的传入参数是:测试客户端4
    
    
                 测试客户端4 接收响应:1548409232.0217009时刻,经过不负责任的socket处理过的数据:测试客户端4
    
    
        发送数据给:<socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34424)>
        -------------------------->>>>>>>>>>>>>>>>执行关闭服务器完毕
        接收到新socket:<socket.socket fd=10, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 34438)>
        服务器执行关闭所有操作  
        
    """
    
    

    相关文章

      网友评论

          本文标题:04协程番外:IO多路复用之select服务器案例第一版

          本文链接:https://www.haomeiwen.com/subject/mwjvjqtx.html