首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我不能理解python中的轮询/选择

我不能理解python中的轮询/选择
EN

Stack Overflow用户
提问于 2011-09-18 12:06:08
回答 3查看 12.7K关注 0票数 13

我正在用python做一些线程异步网络实验,使用UDP。

我想了解轮询和选择python模块,我从未在C/C++中使用过它们。

这些是用来做什么的?我有点理解select,但它在查看资源时会阻塞吗?轮询的目的是什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-18 16:39:19

如果你使用readrecv,你只需要等待一个连接。如果您有多个连接,则必须创建多个进程或线程,这是对系统资源的浪费。

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

它可以无限阻塞,在给定的时间内阻塞,或者根本不阻塞,这取决于参数。

票数 11
EN

Stack Overflow用户

发布于 2015-03-28 16:58:24

好的,一次一个问题。

这些是用来做什么的?

下面是一个简单的socket服务器框架:

代码语言:javascript
运行
复制
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 可能需要很长时间,甚至包含一个循环(通常是这样)

代码语言:javascript
运行
复制
def process_client_sock(c_sock, c_addr):
    while True:
        receive_or_send_data(c_sock)

在这种情况下,服务器不能接受更多的连接。

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

代码语言:javascript
运行
复制
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和内存,所以没有空闲的服务器可能会获得数千个连接。

因此,selectpoll系统调用试图解决这个问题。您为select提供了一组文件描述符,并告诉它在任何fd准备好读/写/或发生异常时通知您。

它(Select)在查看资源时会阻塞吗?

“是”或“否”取决于传递给它的参数。

正如select man page所说,它将获取struct timeval参数

代码语言:javascript
运行
复制
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 */
};

有三种情况:

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

No-阻塞,返回immediately

  • timeout == NULL

在文件描述符为ready.

  • timeout之前永远阻塞是正常的

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

轮询的目的是什么?

简单地说:在等待IO时,轮询将释放CPU用于其他工作。

这是基于一个简单的事实:

  1. CPU比IO
  2. waiting快得多,因为IO非常浪费时间,因为在大多数情况下,CPU都是idle

希望能有所帮助。

票数 14
EN

Stack Overflow用户

发布于 2013-12-14 03:46:13

select()接受3个套接字列表以检查三个条件(读取、写入、错误),然后返回(通常较短,通常为空)套接字列表,这些套接字列表实际上已准备好针对这些条件进行处理。

代码语言:javascript
运行
复制
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind((Local_IP, Port1))
s1.listen(5)

s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind((Local_IP, Port2))
s2.listen(5)

sockets_that_might_be_ready_to_read = [s1,s2]
sockets_that_might_be_ready_to_write_to = [s1,s2]
sockets_that_might_have_errors = [s1,s2]


([ready_to_read], [ready_to_write], [has_errors])  = 
       select.select([sockets_that_might_be_ready_to_read],
                     [sockets_that_might_be_ready_to_write_to], 
                     [sockets_that_might_have_errors],            timeout)


for sock in ready_to_read:
    c,a = sock.accept()
    data = sock.recv(128)
    ...
for sock in ready_to_write:
    #process writes
    ...
for sock in has_errors:
    #process errors

因此,如果一个套接字在等待超时秒后没有尝试连接,那么列表ready_to_read将为空--此时,accept()和recv()是否阻塞都无关紧要--它们不会被调用为空的列表……

如果套接字准备好读取,那么If就会有数据,所以它也不会阻塞。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7459408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档