【问题标题】:Any reason why socket.send() hangs?socket.send() 挂起的任何原因?
【发布时间】:2009-08-09 08:57:13
【问题描述】:

我正在用 Python 编写一个迷你 FTP 服务器,它像 FTP 一样公开底层数据库。流程是这样的:

sock.send("150 Here's the file you wanted\r\n")
proc = Popen2(...)
for parts in data:
    data_sock.send(parts)
proc.kill()
sock.send("226 There's the file you wanted\r\n")
data_sock.shutdown(0)
data_sock.close()

data_sock 是已启动并工作的 PASV 套接字,由 Wireshark 确认。实际发生的情况是在第 163,328 个字节通过 data_sock 发送后,data_sock.send() 行就挂起。我怀疑发送缓冲区已满,但我不明白为什么 FTP 客户端不会从 PASV 套接字读取数据。

我已经包含了 Popen2(...) 行,因为我已经设法在 OS X 上重现 http://bugs.python.org/issue3006 ——在 Popen 进程被终止之前,套接字不会关闭。不确定这是否有某种关系。

【问题讨论】:

    标签: python sockets ftp


    【解决方案1】:

    很难从这个代码片段中说并且不知道客户端,但是您发送 150(指示新数据通道)而不是 125(指示使用现有数据通道)是否可能会使客户端感到困惑,它只是还没开始读取数据?

    您是否看过 pyftpdlib 作为滚动您自己的服务器的替代方案?

    【讨论】:

      【解决方案2】:

      我在客户端上传时遇到了类似的问题,这似乎可以追溯到调制解调器/路由器阻塞——我目前唯一的解决方法是限制传输速率(发送 128 字节,睡眠约 50 毫秒,重复)。

      【讨论】:

      • 我在本地主机上测试两端。也许这是错误的,但我的心智模型表明,在优先级相同的情况下,发送/接收的速度应该差不多,不是吗?
      【解决方案3】:

      客户端可能停止读取数据的一个原因是有人在传输过程中拔掉了客户端(或断开了其以太网电缆)。在这种情况下,TCP 将保持(不成功)重新发送数据包几分钟,没有得到响应,直到它放弃。还有其他可能的原因。

      由于如果您想要一个强大的服务器,您必须处理上述可能性,因此真正的问题不一定是它为什么会发生,而是当它发生时您应该做什么。一些可能的事情是:

      1. 确保客户端没有任何导致它们停止读取的错误,即使数据可用
      2. 确保服务器不会阻塞,即使特定连接的 send() 调用确实阻塞(您可以通过 select()/poll() 和非阻塞套接字或可能通过多线程来完成此操作...我如果可能,推荐前者)
      3. 在 select() 中添加一些超时逻辑,这样如果超过 (N) 秒后,套接字已准备好发送数据但实际上并未发送,服务器就会放弃并关闭套接字。 (TCP 自己会这样做,但 TCP 的超时时间可能对你的口味来说太长了)

      【讨论】:

        猜你喜欢
        • 2012-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-10
        • 2019-04-30
        • 2011-02-19
        • 2011-12-22
        相关资源
        最近更新 更多