2012-12-05 68 views
1

我在python中構建了客戶端 - 服務器體系結構,不幸的是,最初的設計是,每個到服務器的請求都由一個TCP連接表示,我必須發送大型組(20 000+)的請求,有時出現插座錯誤#10055WinSock錯誤#10055

我已經發現瞭如何處理它在python:

>>> errno.errorcode[10055] 
'WSAENOBUFS' 
>>> errno.WSAENOBUFS 
10055 

,並建立一個代碼,能夠處理錯誤,並重新連接(當然,很少有時間延遲給服務器的時間做不管它必須做):

class MyConnect: 
    # __init__ and send are not important here 

    def __enter__(self): 
     self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

     # Try several reconnects 
     for i in range(0,100): 
      try: 
       self.sock.connect((self.address, self.port)) 
       break 

      except socket.error as e: 
       if e.errno == errno.WSAENOBUFS: 
        time.sleep(1) 
       else: 
        raise 

     return self 

    def __exit__(self, type, value, traceback): 
     self.sock.close() 

# Pseudocode 
for i in range(0,20000): 
    with MyConnect(ip,port) as c: 
     c.send(i) 

我的問題是:

  • 沒有任何「好習慣「這樣做的方法?
  • e.errno == errno.WSAENOBUFS多平臺?如果不是這樣,如何使它成爲多平臺?

注意:我在剛剛測試在Windows然而,我需要它在Linux上工作了。

+0

你是說你需要同時擁有20000個TCP連接到同一個地址/端口嗎?你可能會首先用完臨時端口。你有沒有考慮過這個問題?設置最大連接數?順便說一句,你關閉了插座? –

+0

「串行」你的意思是你有一次打開一個連接?這不是你在代碼中所擁有的。 –

+0

@NikolaiNFetissov我已經編輯了我的問題(和nuked舊評論),現在你幾乎已經使用了我正在使用的確切代碼 – Vyktor

回答

2

您正在使用外發數據和所有連接建立和終止數據包堵塞TCP堆棧。

如果堅持這個設計,然後強制每個連接靈兒,直到它的數據已成功發送。也就是說,默認情況下,套接字上的close()立即返回,並且進一步的傳遞嘗試和連接拆除「在後臺」發生。您可以看到,在緊密的循環中這樣做超過20000次可能會輕易地淹沒OS網絡堆棧。

下面將迫使你的插座close()掛在長達10秒試圖分發數據:

import struct 
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 10)) 

注意,這是不一樣的Python socket.sendall() - 一個剛剛通過了所有字節到內核​​。

希望這會有所幫助。

+0

這是很好的答案,但我還有一個問題(出於好​​奇,可能不會實現)。比方說,我會有非常沉重的負載服務器,我希望客戶端就像這樣'如果套接字。錯誤== server_heavy_load(10055):在幾秒鐘後重試'我怎麼能做到這個多平臺(nix&windows足夠了; windows已經被我最初發布的代碼處理過了)。 – Vyktor

+1

你將會碰到不同的TCP堆棧的黑暗角落,這裏沒有單一的標準錯誤條件。你必須測試,在每個平臺上打印出'errno'。 –