linu平台下使用poll 和 epoll实现高并发

poll 和 epoll

poll只是简单对select进行了优化,但是还不够完美 ,epoll才是最后的解决方案

注意:epoll仅能在linux中使用

案例:

import socket
import select

s = socket.socket()
s.bind(("127.0.0.1",1689))
s.listen()

# 创建一个epoll对象
epoll = select.epoll()

# 注册读就绪事件 (有数据可以读取了)
# s.fileno()用于获取文件描述符
epoll.register(s.fileno(),select.EPOLLIN)


# 存储文件描述符与socket的对应关系
fd_sockets = {s.fileno():s}


while True:
    # 该函数是阻塞会直到你关注的事件发生
    # 返回值为文件描述符与发生的事件类型  是一个列表 列表中是元组  第一个是描述符 第二个是事件
    for fd,event in epoll.poll():
        print("有socket 搞事情了!")
        sock = fd_sockets[fd] # 取出对应的socket对象

        # 判断socket是服务器还是客户端
        if sock == s:
            # 执行对应的接收或发送
            client,addr = sock.accept()
            # 注册客户端的事件
            epoll.register(client.fileno(),select.EPOLLIN)
            # 将对应关系存储到字典中
            fd_sockets[client.fileno()] = client
            print("来了一个客户端....")
            
        elif event == select.EPOLLIN: #客户端的处理
            data = sock.recv(1024)
            if not data:
                epoll.unregister(fd) # 注销事件
                fd_sockets.pop(fd) # 从字典中删除
                sock.close()  # 关闭socket
                continue

            print("%s 发来问候:%s" % (sock,data.decode("utf-8")))

            #将事件转换为可写
            epoll.modify(fd,select.EPOLLOUT)
        else:
            sock.send("我是服务器  你丫是谁?".encode("utf-8"))
            # 将事件转换为可读
            epoll.modify(fd, select.EPOLLIN)

epoll 如何解决select的两个问题

1.epoll 把对于等待队列的操作 与阻塞进程分开了

2.epoll 自己维护了一个等待队列 避免了遍历所有socket

posted @ 2019-07-12 17:00  emos  阅读(275)  评论(0编辑  收藏  举报