美文网首页程序员
python 多路复用IO select服务器模型 epoll服

python 多路复用IO select服务器模型 epoll服

作者: L_Leisure | 来源:发表于2018-12-15 16:10 被阅读2次

    python 的select服务器模型

    python提供了操作系统底层select接口的封装版本,使用起来会更加方便。

    select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
    

    rlist wlist xlist都是列表数据结构。返回的列表则是对应的可读表,可写表,有异常表。

    import select
    from socket import *
    
    
    def main():
        # 1. 创建socket套接字
        tcp_server = socket(AF_INET, SOCK_STREAM)
        # 2. 绑定IP地址和端口
        tcp_server.bind(("", 6699))
        # 3. 把主动模式变成被动模式 只能接收 不能发送数据
        tcp_server.listen(5)
        # 4. 声明一个列表
        inputs_list = [tcp_server]
        while True:
            # 阻塞在这里,内核监听inputs_list里的套接字,如果状态改变就进行解阻塞, 并返回有变化的套接字
            read_list, _, _ = select.select(inputs_list, [], [])
            # 循环read_list
            for sock in read_list:
                # 判断是不是被动的套接字
                if sock == tcp_server:
                    # 创建新的套接字
                    new_socket, client_info = sock.accept()
                    # 将创建好的套接字添加到列表中
                    inputs_list.append(new_socket)
                    print(f"连接到{client_info}")
                else:
                    # 接收数据
                    raw_data = sock.recv(1024)
                    if raw_data:
                        # 发送数据
                        sock.send(raw_data)
                        print(f"收到{client_info}的数据{raw_data.decode('gb2312')}")
                    else:
                        # 断开连接
                        sock.close()
                        # 将套接字从列表中移除
                        inputs_list.remove(sock)
    
    
    if __name__ == '__main__':
        main()
    
    
    1. 32系统只能1024个连接 64位 2048个

      2.采用轮询机制,当并发大的时候,就会崩了

    ​ POLL只是突破了连接的限制

    python 的epoll服务器模型

    为了解决select和poll轮询机制的效率问题,从Linux2.6内核开始,引入了epoll接口。

    没有最大并发连接的限制,能打开的文件描述符的上限远大于1024。

    效率提升,不是轮询的方式,而是采用了事件通知机制,当文件描述符配置为epoll方式后,一旦事件发生,设备驱动会主动通知内核,此时应用空间会得到通知。

    应用空间的处理机制几乎不变,主要是内核结构的修改。

    from socket import *
    import select
    
    
    def main():
        # 创建socket套接字
        tcp_server = socket(AF_INET, SOCK_STREAM)
        # 重复使用绑定的信息
        tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        # 绑定端口,ip
        tcp_server.bind(("", 6699))
        # 把主动模式变为被动模式,只能接收,不能发送数据
        tcp_server.listen(5)
        # 创建epoll()对象
        epoll = select.epoll()
        # 将被动套接字添加到epoll对象中
        print(f"被动套接字:{tcp_server.fileno()}")
        epoll.register(tcp_server.fileno(), select.EPOLLIN)
        # 声明一个字典,用来存储新的套接字
        new_sockets = {}
        # 声明一个字典,用来存储客户端信息
        client_infos = {}
        while True:
            print(f"所有新的套接字{new_sockets}")
            print(f"所有客户端信息{client_infos}")
            # 阻塞在这里,等待套接字状态改变
            epoll_list = epoll.poll()
            print(f"epoll_list:{epoll_list}")
            # 循环epoll_list
            for fd, events in epoll_list:
                print(f"fd:{fd},events:{events}")
                # 判断fd是不是被动套接字
                if fd == tcp_server.fileno():
                    # 创建新的套接字
                    new_socket, client_info = tcp_server.accept()
                    print(f"连接到{new_socket}")
                    # 将新的套接字接入到epoll监听列表
                    epoll.register(new_socket.fileno(), select.EPOLLIN)
                    # 将新的套接字存入字典
                    new_sockets[new_socket.fileno()] = new_socket
                    # 将新的客户端存入字典
                    client_infos[new_socket.fileno()] = client_info
                else:
                    # 接收信息
                    raw_data = new_sockets[fd].recv(1024)
                    # 判断
                    if raw_data:
                        print(f"收到{client_infos[fd]}的数据{raw_data.decode('gb2312')}")
                    else:
                        # 关闭套接字
                        new_sockets[fd].close()
                        # 注销监听队列
                        epoll.unregister(fd)
                        # 字典删除
                        del new_sockets[fd]
                        del client_infos[fd]
    
    
    if __name__ == '__main__':
        main()
    
    

    相关文章

      网友评论

        本文标题:python 多路复用IO select服务器模型 epoll服

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