WinSock错误#10055

时间:2012-12-05 09:46:00

标签: python sockets error-handling python-3.x multiplatform

我在python中构建了客户端 - 服务器体系结构,遗憾的是原始设计是每个服务器请求都由一个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上运行。

1 个答案:

答案 0 :(得分: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()不同 - 只是将所有字节传递给内核。

希望这有帮助。