我正在使用 UDP 在 python 中进行一些线程异步网络实验。
我想了解轮询和选择 python 模块,我从未在 C/C++ 中使用过它们。
那些是做什么用的?我有点理解选择,但它会在观看资源时阻塞吗?投票的目的是什么?
最佳答案
好的,一次一个问题。
这些是做什么用的?
这是一个简单的套接字服务器框架:
s_sock = socket.socket()
s_sock.bind()
s_sock.listen()
while True:
c_sock, c_addr = s_sock.accept()
process_client_sock(c_sock, c_addr)
服务器会循环接受来自客户端的连接,然后调用其处理函数与客户端套接字进行通信。这里有一个问题:process_client_sock
可能需要很长时间,甚至包含一个循环(这是经常发生的情况)。
def process_client_sock(c_sock, c_addr):
while True:
receive_or_send_data(c_sock)
在这种情况下,服务器无法再接受任何连接。
一个简单的解决方案是使用多进程或多线程,只需创建一个新线程来处理请求,同时主循环继续监听新连接。
s_sock = socket.socket()
s_sock.bind()
s_sock.listen()
while True:
c_sock, c_addr = s_sock.accept()
thread = Thread(target=process_client_sock, args=(c_sock, c_addr))
thread.start()
这当然有效,但考虑到性能还不够好。因为新进程/线程需要额外的 CPU 和内存,服务器不空闲可能会获得数千个连接。
因此select
和poll
系统调用试图解决这个问题。您给 select
一组文件描述符,并告诉它在任何 fd 准备好读/写/或发生异常时通知您。
它(选择)在观看资源时会阻塞吗?
是或否取决于您传递给它的参数。
作为select man page说,它将获得 struct timeval
参数
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
分三种情况:
timeout.tv_sec == 0 和 timeout.tv_usec = 0
无阻塞,立即返回
超时 == NULL
永远阻塞,直到文件描述符准备就绪。
超时是正常的
等待一定时间,如果仍然没有可用的文件描述符,则超时返回。
投票的目的是什么?
简单来说:在等待 IO 时,轮询可以释放 CPU 用于其他工作。
这是基于一个简单的事实
- CPU 比 IO 快得多
- 等待IO是浪费时间,因为大部分时间,CPU都会空闲
希望对您有所帮助。
关于python - 我无法理解 python 中的轮询/选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7459408/