【问题标题】:WinSock error #10055WinSock 错误 #10055
【发布时间】:2012-11-23 02:29:04
【问题描述】:

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

【问题讨论】:

  • 你是说你“需要”同时有 20000+ 个 TCP 连接到同一个地址/端口吗?您可能首先会用完临时端口。你有没有考虑过这样的节奏?设置最大连接数?顺便说一句,你要关闭套接字吗?
  • “串行”是指一次打开一个连接?这不是您在代码中的内容。
  • @NikolaiNFetissov 我已经编辑了我的问题(并删除了旧评论),现在你几乎有了我正在使用的确切代码
  • 嗯,恐怕这就是你滥用 TCP 的结果。在同一个连接上完成所有这些操作会干净得多。现在你有大量的连接建立和拆除开销。
  • @NikolaiNFetissov 我已经做到了“干净的方式”(给予或花费几分钟的调试时间),但我仍在寻找一种在多个平台上处理此错误并正确反应的正确方法给它。

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


【解决方案1】:

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

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

以下内容将强制您的套接字close() 挂起最多 10 秒以尝试传递数据:

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

请注意,这与 Python socket.sendall() 不同 - 它只是将所有字节传递给内核。

希望这会有所帮助。

【讨论】:

  • 这是一个很好的答案,但我还有一个问题(只是出于好奇,可能不会真正实现它)。假设我的服务器负载非常重,我希望客户端像这样if socket.error == server_heavy_load (10055): retry after few seconds 我该怎么做那个多平台(nix 和 windows 就足够了;windows 已经由我最初发布的代码处理)。
  • 您将遇到不同 TCP 堆栈的黑暗角落,这里没有单一的标准错误条件。你必须测试,在每个平台上打印出errno
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多