我无法理解python中的轮询/选择

jok*_*oon 13 python sockets multithreading epoll polling

我正在使用UDP在python中进行一些线程异步网络实验.

我想了解polling和select python模块,我从未在C/C++中使用它们.

这些是为了什么?我有点理解,但在观看资源时会阻止吗?民意调查的目的是什么?

ciz*_*ixs 11

好的,一次一个问题.

这些是为了什么?

这是一个简单的套接字服务器框架:

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)
Run Code Online (Sandbox Code Playgroud)

服务器将循环并接受来自客户端的连接,然后调用其进程函数与客户端套接字进行通信.这里有一个问题:process_client_sock可能需要很长时间,甚至包含一个循环(通常就是这种情况).

def process_client_sock(c_sock, c_addr):
    while True:
        receive_or_send_data(c_sock)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,服务器无法再接受任何连接.

一个简单的解决方案是使用多进程或多线程,只需创建一个新线程来处理请求,而主循环继续监听新连接.

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()
Run Code Online (Sandbox Code Playgroud)

这当然有效,但考虑到性能还不够好.因为新进程/线程需要额外的CPU和内存,所以服务器不空闲可能会获得数千个连接.

因此select,poll系统调用尝试解决此问题.您提供select了一组文件描述符,并告诉它是否有任何fd准备好读/写/或发生异常时通知您.

在观看资源时是否(选择)阻止?

是或否取决于您传递给它的参数.

选择手册页所示,它将获得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 */
};
Run Code Online (Sandbox Code Playgroud)

有三种情况:

  1. timeout.tv_sec == 0和timeout.tv_usec = 0

    无阻塞,立即返回

  2. 超时== NULL

    永远阻止,直到文件描述符准备好.

  3. 超时是正常的

    等待一定时间,如果仍然没有文件描述符可用,则超时并返回.

民意调查的目的是什么?

简而言之:轮询在等待IO时为其他工作释放CPU.

这是基于简单的事实

  1. CPU比IO更快
  2. 等待IO是浪费时间,因为在最多的时候,CPU会闲置

希望能帮助到你.


chy*_*hys 10

如果你这样做read或者recv,你就等着上只有一个连接.如果您有多个连接,则必须创建多个进程或线程,这会浪费系统资源.

使用selectpollepoll,您可以仅使用一个线程监视多个连接,并在其中任何一个有可用数据时收到通知,然后您调用readrecv在相应的连接上.

它可以无限阻塞,阻塞给定时间,或者根本不阻塞,具体取决于参数.