1

私はPythonでクライアントサーバーアーキテクチャを構築していますが、残念ながら、サーバーへの各リクエストが1つのTCP接続で表されるという元の設計が行われ、大きなグループ(20 000以上)でリクエストを送信する必要があり、ソケットエラーが発生することがあります#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でも動作する必要があります。

4

1 に答える 1

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()、すべてのバイトをカーネルに渡すだけです。

お役に立てれば。

于 2012-12-06T17:24:00.290 に答える