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的客户端测试完全相同。