我相信你可以通過在操作系統級別調整您的TCP設置擺脫掛狀態,但假設您的應用程序不會在專用(並由您維護)機器上工作,您應該尋求更通用的解決方案。
你問:
是否有可能只在沒有數據發送超時通過插座/收到了一定的時間也許
而這正是行爲socket.settimeout
(或傳遞給urllib2
的那個)會給你。與基於SIGALRM的超時(即使在數據傳輸緩慢時會終止)相反,只有在定義的時間段內沒有數據傳輸時,傳遞到套接字的超時纔會發生。如果socket.send
或socket.recv
的呼叫應該返回部分計數,如果在此期間某些(但不是全部)數據已傳輸,並且urllib2
然後將使用後續呼叫來傳輸剩餘數據。
說了這樣的話,如果POST調用將在多個send
調用中執行,並且任何(但不是第一個)調用都會在不發送任何數據的情況下阻塞並超時,那麼您的POST調用仍可能在上傳中途的某個地方終止。您給人的印象是它不會被您的應用程序正確處理,但我認爲它應該,因爲它類似於強制終止該流程或者簡單地將連接斷開。
您是否測試過並確認socket.settimeout
不能解決您的問題?或者你只是不確定行爲是如何實施的?如果前者是正確的,請你提供更多的細節?我相當肯定你只需設置超時時間是安全的,因爲python只是使用低級BSD套接字實現,其行爲如上所述。爲了給您更多的參考,請看setsockopt
手冊頁和SO_RCVTIMEO
或SO_SNDTIMEO
選項。我期望socket.settimeout
恰好使用這些功能和選項。
---編輯---(提供一些測試代碼)
所以我能夠得到Requests
模塊和測試與urllib2
沿着行爲。我已經運行了服務器,它在每個recv
調用之間增加間隔接收數據塊。如預期的那樣,當間隔達到指定的超時時間時,客戶端超時。例如:
服務器
import socket
import time
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.bind(("localhost", 12346))
listener.listen(1)
sock,_ = listener.accept()
interval = 0.5
while 1:
interval += 1 # increase interval by 1 second
time.sleep(interval)
# Get 1MB but will be really limited by the buffer
data = sock.recv(1000000)
print interval, len(data)
if not data:
break
客戶(請求模塊)
import requests
data = "x"*100000000 # 100MB beefy chunk
requests.post("http://localhost:12346", data=data, timeout=4)
客戶(urllib2的模塊)
import urllib2
data = "x"*100000000 # 100MB beefy chunk
urllib2.urlopen("http://localhost:12346", data=data, timeout=4)
輸出(服務器)
> 1.5 522832
> 2.5 645816
> 3.5 646180
> 4.5 637832 <--- Here the client dies (4.5 seconds without data transfer)
> 5.5 294444
> 6.5 0
兩個客戶提出的異常:按預期工作
# urllib2
URLError: timeout('timed out',)
# Requests
Timeout: TimeoutError("HTTPConnectionPool(host='localhost', port=12346): Request timed out. (timeout=4)",)
一切!如果不通過超時作爲參數,urllib2
也反應良好socket.setdefaulttimeout
,但Requests
沒有。這並不令人驚訝,因爲內部實現根本不需要使用默認值,並且可以根據傳遞的參數或使用非阻塞套接字簡單地覆蓋它。
我一直在使用運行此如下:
OSX 10.8.3
Python 2.7.2
Requests 1.1.0
首先 - *爲什麼*它永遠阻擋? – 2013-03-18 16:58:46
@CodePainters我不知道 - 理想情況下,我會解決實際問題,我會繼續嘗試,但它可能是一個服務器端問題(我不控制),直到我找到原因, d喜歡設置一些作爲後備的東西,以便上傳永遠不會凍結,並在此期間作爲修補程序發佈。 – GP89 2013-03-18 17:02:38