socket.send()挂起的原因是什么?

时间:2009-08-09 08:57:13

标签: python sockets ftp

我正在用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确认。实际发生的是在通过data_sock发送了第163,328个字节后,data_sock.send()行才挂起。我怀疑发送缓冲区已满,但对我来说,为什么FTP客户端不会从PASV套接字读取,这是一个谜。

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

3 个答案:

答案 0 :(得分:1)

很难说这个代码片段并且不知道客户端,但是您发送150(表示新数据通道)而不是125(表示使用现有数据通道)可能会混淆客户端,它只是不开始阅读数据?

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

答案 1 :(得分:0)

我在客户端遇到类似的上传问题,似乎跟踪调制解调器/路由器的窒息 - 我现在唯一的工作就是限制传输速率(发送128个字节,睡眠~50ms) ,重复)。

答案 2 :(得分:0)

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

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

  1. 确保客户端没有任何导致他们停止阅读的错误,即使数据可用
  2. 确保即使特定连接的send()调用阻止服务器也不会阻塞(您可以通过select()/ poll()和非阻塞套接字执行此操作,或者可能通过多线程执行... I如果可能,推荐前者)
  3. 为select()添加一些超时逻辑,这样如果超过(N)秒,则套接字有数据准备发送但实际上没有发送,服务器放弃并关闭套接字。 (TCP自己这样做,但TCP的超时时间可能太长,不符合您的口味)