1

我在 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 上工作。

4

1 回答 1

2

您正在用传出数据以及所有连接建立和终止数据包阻塞您的 TCP 堆栈。

如果您必须坚持这种设计,则强制每个连接都在其数据发送成功之前逗留。也就是说,默认情况下,close()套接字立即返回,进一步的传递尝试和连接断开发生在“后台”。您可以看到,在紧密循环中执行超过 20000 次以上的操作很容易使操作系统网络堆栈不堪重负。

以下将强制您的套接字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 回答