【发布时间】:2012-10-15 07:40:38
【问题描述】:
我这样编写客户端-服务器应用程序: 客户端(c#) 服务器(扭曲;ftp 代理和附加功能) ftp 服务器
Server 有两个类:我自己的类协议继承自 LineReceiever 协议和 FTPClient 继承自 twisted.protocols.ftp。
但是当客户端发送或获取大文件(10 Gb - 20 Gb)时,服务器会捕获 MemoryError。我的代码中没有使用任何缓冲区。当调用 transport.write(data) 数据附加到反应器编写器的内部缓冲区时会发生这种情况(如果我错了,请纠正我)。
我应该使用什么来避免这个问题?还是我应该改变解决问题的方法?
我发现对于大流,我应该使用 IConsumer 和 IProducer 接口。但最后它会调用 transfer.write 方法,效果是一样的。还是我错了?
UPD:
这是文件下载/上传的逻辑(从 ftp 通过 Twisted 服务器到 Windows 上的客户端):
客户端向 Twisted 服务器发送一些标头,然后开始发送文件。 Twisted 服务器接收标头,然后(如果需要)调用setRawMode(),打开 ftp 连接并从/向客户端接收/发送字节,并在所有关闭连接之后。下面是上传文件的部分代码:
FTPManager 类
def _ftpCWDSuccees(self, protocol, fileName):
self._ftpClientAsync.retrieveFile(fileName, FileReceiver(protocol))
class FileReceiver(Protocol):
def __init__(self, proto):
self.__proto = proto
def dataReceived(self, data):
self.__proto.transport.write(data)
def connectionLost(self, why = connectionDone):
self.__proto.connectionLost(why)
主代理服务器类:
class SSDMProtocol(LineReceiver)
...
在 SSDMProtocol 对象(调用 obSSDMProtocol)解析标头后,它调用打开 ftp 连接的方法(FTPClient 来自 twisted.protocols.ftp)并设置 FTPManager 字段的对象 _ftpClientAsync 并调用 _ftpCWDSuccees(self, protocol, fileName) 和 protocol = obSSDMProtocol 以及何时文件的字节recieved 调用 FileReceiver 对象的dataReceived(self, data)。
当self.__proto.transport.write(data) 被调用时,数据附加到内部缓冲区比发送回客户端更快,因此内存耗尽。当缓冲区达到一定大小时我可以停止读取并在缓冲区全部发送到客户端后恢复读取?或类似的东西?
【问题讨论】:
标签: twisted file-transfer