• python的select和epoll


    python的select和epoll

    1.select模型:

    • linux中每个套接字都是文件,都有唯一的文件描述符,这些设备的文件描述符被放在一个数组中,然后select调用的时候遍历这个数组,如果对于的文件描述符可读则会返回改文件描述符。当遍历结束之后,如果仍然没有一个可用设备文件描述符,select让用户进程则会睡眠,直到等待资源可用的时候在唤醒,遍历之前那个监视的数组。每次遍历都是以轮询的方式依次进行判断的。

    select实现回显服务器:

    
    from socket import *
    from select import *
    
    s = socket(2,1)
    s.setsockopt(1,2,1)
    s.bind(('',8080))
    s.listen(1024)
    
    s_list = [s.fileno(),]  #fileno()获取套接字的唯一描述符,每个套接字都是唯一不同的
    s_dict = {}
    
    while 1:
        list_readable,a,b = select(s_list,[],[]) #分别对应: 输入,输出,错误输出
        for i in list_readable:
            if i == s.fileno():
                conn,userinfo = s.accept()
                s_list.append(conn.fileno())
                s_dict[conn.fileno()] = conn
            else:
                cs = s_dict[i]
                recv_data = cs.recv(1024)
                if len(recv_data) <= 0:
                    s_dict[i].close()
                    s_dict.pop(i)
                    s_list.remove(i)
                else:
                    cs.send(recv_data)
    
    

    2.epoll模型:

    • select模型会受到文件描述符数量的限制,所以一般最多是1024个套接字,而epoll突破了此限制。
    • epoll采用的是事件通知机制,而不再是以轮询的方式挨个询问每个文件描述符的状态,节省cpu时间。
    • epoll是select的进阶版。一般情况下epoll效率更高

    epoll实现回显服务器:

    
    from socket import *
    from select import *
    
    s = socket(2,1)
    s.setsockopt(1,2,1)
    s.bind(('',8080))
    s.listen(1024)
    
    s_dict = {}
    
    epoll_instance = epoll()
    epoll_instance.register(s.fileno(),EPOLLIN|EPOLLET)
    while 1:
        epoll_list = epoll_instance.poll()
        for fd,event in epoll_list:
            if fd == s.fileno():
                cs,userinfo = s.accept()
                epoll_instance.register(cs.fileno(),EPOLLIN|EPOLLET)
                s_dict[cs.fileno()] = cs
            else:
                cs = s_dict[fd]
                recv_data = cs.recv(1024)
                print(recv_data.decode('gb2312'))
                if len(recv_data) > 0 :
                    cs.send(recv_data)
                else:
                    print('adsfasdf')
                    epoll_instance.unregister(fd)
                    cs.close()
                    s_dict.pop(fd)
                
    
    • 注:EPOLLIN(可读),EPOLLOUT(可写)
    • EPOLLET: 边缘触发模式(只通知一次)
    • EPOLLLT:水平触发模式(通知后没有做处理的话还会继续通知)

  • 相关阅读:
    用PYTHON修改电脑IP地址
    PYTHON os 模块详解
    django 笔记
    PYTHON实战目录
    群晖PLEX设置方法
    jellin docker 群晖设置方法转自先生
    PYTHON ftp 上传方法
    打包驱动EXSI
    我的PYTHON老师ALEX
    安装WHELL
  • 原文地址:https://www.cnblogs.com/PrettyTom/p/6626229.html
Copyright © 2020-2023  润新知