2010-04-27 114 views
75

我需要在python的套接字recv方法上设置超时。怎么做?如何在python的套接字recv方法上设置超时?

+1

如果FYI你确实选择使用超时...你需要知道如何处理超时。这太问题有关处理谈判时发生超时:https://stackoverflow.com/questions/16745409 – 2017-11-21 16:25:17

回答

37
+10

它不超时的的recv(至少在我尝试了)。只有accept()超时。 – 2011-06-01 11:40:16

+6

在完全按照预期设置socket.settimeout()后,socket.recv()似乎超时了。我在做这个吗?其他人能证实这一点吗? – Aeonaut 2011-10-23 03:20:49

+3

@Aeonaut我认为这段时间大部分时间都是recv(),但是有一个竞争条件。在socket.recv()中,Python(2.6)使用超时在内部调用select/poll,然后立即调用recv()。所以如果你使用阻塞套接字,并且在这两个调用之间另一个端点崩溃,你可能会无限期地挂在recv()上。如果你使用非阻塞套接字,python不会在内部调用select.select,所以我认为Daniel Stutzbach的答案是正确的。 – 2012-08-04 08:51:31

88

典型的方法是使用select()要等到数据可用,或者直到超时发生。只有当数据实际可用时才致电recv()。为了安全起见,我们还将套接字设置为非阻塞模式,以确保recv()永远不会无限期地阻塞。 select()也可用于一次等待多个套接字。

import select 

mysocket.setblocking(0) 

ready = select.select([mysocket], [], [], timeout_in_seconds) 
if ready[0]: 
    data = mysocket.recv(4096) 

如果你有大量的打开的文件描述符,poll()是一种更有效的替代select()

另一种选择是设置超时使用socket.settimeout()插座上的所有操作,但我看到你已经明确拒绝了另一个答案是解决方案。

+12

使用'select'是好的,但如果你说“你不能”的部分是误导性的,因为有'socket.settimeout()'。 – nosklo 2010-04-28 16:41:10

+1

@nosklo我已经更新了我的答案。 – 2010-04-28 16:51:54

+0

现在好多了,但我没有看到答案被“明确拒绝”的地方。 – nosklo 2010-04-28 18:31:51

18

如前所述既select.select()socket.settimeout()会工作。

注意您可能需要调用settimeout两次您的需求,例如

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
# accept can throw socket.timeout 
sock.settimeout(5.0) 
conn, addr = sock.accept() 

# recv can throw socket.timeout 
conn.settimeout(5.0) 
conn.recv(1024) 
+2

我认为,无论你如何捅捅这个功能,他都会遇到同样的事情。我已经尝试了2或4个超时,现在仍然挂起。 settimeout也会挂起。 – 2014-09-30 22:19:28

+0

当你多次调用'.settimeout()'时,你可以首先调用'setdefaulttimeout()'方法。 – mvarge 2016-11-17 21:40:43

9

你可以接收到响应之前,并在收到响应后设置超时设置回无:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

sock.settimeout(5.0) 
data = sock.recv(1024) 
sock.settimeout(None) 
0

试试这个,它使用的基本C.

timeval = struct.pack('ll', 2, 100) 

s.setsockopt(socket.SOL_SOCKET,SO_RCVTIMEO, timeval) 
相关问题