Python非阻塞网络通信Howto

在Python中,你使用socket.setblocking(0)使它无阻塞。在C中,它更复杂,(一方面,你需要在BSD风格O_NONBLOCK和几乎不可区分的Posix风味O_NDELAY之间进行选择,这完全不同于TCP_NODELAY),但它是完全相同的想法。你在创建套接字之后,但在使用之前这样做。 (实际上,如果你坚果,你可以来回切换。)

主要的机械差异是send,recv,connect和accept可以返回而没有做任何事情。你有(当然)一些选择。你可以检查返回码和错误代码,一般驱使自己疯了。如果你不相信我,试试它。你的应用程序将增长,bug和吸CPU。所以,让我们跳过脑死亡的解决方案,make it right。

使用select。

在C中,select编码相当复杂。 在Python中,它很简单,而且它足够接近C版本,如果你理解在Python中的select,你会有很少的麻烦在C

ready_to_read, ready_to_write, in_error = \
               select.select(
                  potential_readers,
                  potential_writers,
                  potential_errs,
                  timeout)

  

你传递选择三个列表:第一个包含您可能想要尝试阅读的所有套接字;第二个所有的套接字你可能想尝试写入,最后一个(通常留空)那些你想检查错误。你应该注意一个套接字可以进入多个列表。选择调用正在阻塞,但您可以给它一个超时。这通常是一个明智的事情 - 给它一个很长的超时(说一分钟),除非你有很好的理由,否则。

作为回报,你会得到三个列表。它们包含实际可读,可写和错误的套接字。这些列表中的每一个都是传入的相应列表的子集(可能为空)。

如果一个套接字在输出可读列表中,您可以像我们一直在这个业务中那样接近,那么该套接字上的recv会返回一些东西。可写列表的想法相同。你可以发送东西。也许不是你想要的,但有些事情比没有好。 (实际上,任何合理健康的套接字将返回为可写 - 它只是意味着出站网络缓冲区空间可用。)

如果你有一个“服务器”套接字,将其放在potential_readers列表中。如果它出现在可读列表中,你的接受(几乎肯定)工作。如果您创建了一个新的套接字以连接到其他人,请将其放在potential_writers列表中。如果它显示在可写的列表中,你有一个体面的机会,它已经连接。

一个非常讨厌的问题与选择:如果在那些输入列表中的插座是一个死了一个讨厌的死亡,选择将失败。然后,你需要循环通过所有这些列表中的每个单独的套接字,并做一个select([sock],[],[],0),直到你找到了坏的。超时为0意味着它不会需要很长时间,但它是丑陋的。

实际上,即使使用阻塞套接字,选择也可以方便。这是一种确定是否阻塞的方法 - 当缓冲区中有某些东西时,套接字返回可读。然而,这仍然不能帮助确定另一端是完成还是只忙于其他事情的问题。

posted on 2017-01-07 11:10  LebronZhang  阅读(801)  评论(0编辑  收藏  举报

导航