2010-04-27 133 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) 
相關問題