python练习18 -- 多路复用poll和epoll

poll类(适用linux和unix)

poll类是select模块中的类,基本用法如下:

select.poll()
功能:创建poll对象
返回值:poll对象
用法:p = select.poll()

p.register(fd,event)
功能:注册关注的IO事件
参数:
        fd 要关注的IO
        event 要关注的IO事件类型
            常用类型:
            POLLIN  读IO事件(rlist)
            POLLOUT 写IO事件(wlist)
            POLLERR 异常IO  (xlist)
            POLLUHP 断开连接
用法:p.register(sockfd, POLLIN|POLLERR)

p.unregister(fd)
功能:取消对IO的关注
参数:IO对象或者IO对象的fileno

event = p.poll()
功能:阻塞等待监控的IO事件
返回值:返回发生的IO
events格式 [(fileno, event), () ...]
每个元组为一个就绪IO,元组第一项是该IO的fileno 第二项是该IO的就绪类型

代码示例:

  • 源代码:poll_server.py
#!/bin/env python3
import select
import socket

sockserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sockserver.bind(("0.0.0.0", 80))
sockserver.listen(3)

fdmap = {sockserver.fileno(): sockserver}   # 建立文件描述符和套接字的对应关系

p = select.poll()
p.register(sockserver, select.POLLIN | select.POLLERR) # 注册套接字的关注事件

while True:
    events = p.poll()
    for fd, event in events:
        if fd == sockserver.fileno():
            client, addr = sockserver.accept()
            print("Connect from ", addr)
            p.register(client, select.POLLIN | select.POLLERR)
            fdmap[client.fileno()] = client
        elif event&select.POLLIN:
            data = fdmap[fd].recv(1024).decode()
            if not data:
                p.unregister(fd)
                fdmap[fd].close()
                del fdmap[fd]
                continue
            print("client: ", data)
            msg = "server send back: %s" % data
            fdmap[fd].send(msg.encode())
  • 启动这个服务器程序:
[root@gyl-baidu python]# chmod +x poll_server.py
[root@gyl-baidu python]# ./poll_server.py

  • 用客户端向服务器发送字符串进行测试:

        1)client1:用nc工具连接服务器,并发送字符串I am client1

[root@gly-tencient ~]#  nc -t 192.168.1.84 80
I am client1
server send back: I am client1

        2)client2: 用nc工具连接服务器,并发送字符串I am client1

[root@bjAli ~]# nc -t 192.168.1.84  80
I am client2
server send back: I am client2

        3)server: 服务器上显示如下:

[root@gyl-baidu python]# ./poll_server.py
Connect from  ('192.168.1.10', 57626)
client:  I am client1

Connect from  ('192.168.1.20', 54960)
client:  I am client2

epoll类(仅适用linux)

epoll的用法类似于poll,但处理IO的效率高于poll,但仅适用于linux平台。

源代码epoll_server.py

#!/bin/env python3
import socket
import select

sockserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sockserver.bind(("0.0.0.0", 80))
sockserver.listen(3)

fdmap = {sockserver.fileno(): sockserver}

p = select.epoll()
p.register(sockserver, select.EPOLLIN | select.EPOLLERR)

while True:
    events = p.poll()
    for fd, event in events:
        if fd == sockserver.fileno():
            client, addr = sockserver.accept()
            print("Connect from ", addr)
            p.register(client, select.EPOLLIN | select.EPOLLERR)
            fdmap[client.fileno()] = client
        elif event&select.EPOLLIN:
            data = fdmap[fd].recv(1024).decode()
            if not data:
                p.unregister(fd)
                fdmap[fd].close()
                del fdmap[fd]
                continue
            print("client: ", data)
            msg = "server send back: %s" % data
            fdmap[fd].send(msg.encode())

客户端测试方法与poll的客户端测试完全相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值