我这样编写客户端-服务器应用程序:client(c#) <-> server (twisted; ftp proxy and additional functional) <-> ftp server
服务器有两个类:我自己的类协议继承自 LineReceiever 协议和 FTPClient 来自 twisted.protocols.ftp。
但是当客户端发送或获取大文件(10 Gb - 20 Gb)时,服务器会捕获 MemoryError。我的代码中没有使用任何缓冲区。当调用 transport.write(data) 数据附加到反应器编写器的内部缓冲区时会发生这种情况(如果我错了,请纠正我)。
我应该用什么来避免这个问题?还是我应该改变解决问题的方法?
我发现对于大流,我应该使用 IConsumer 和 IProducer 接口。但最后它会调用 transfer.write 方法,效果是一样的。还是我错了?
升级版:
这是文件下载/上传的逻辑(从 ftp 通过 Twisted 服务器到 Windows 上的客户端):
客户端向 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
from twisted.protocols.ftp
)并设置 FTPManager 字段 _ftpClientAsync 的对象_ftpCWDSuccees(self, protocol, fileName)
并protocol = obSSDMProtocol
在文件的字节收到时调用dataReceived(self, data)
FileReceiver 对象的调用。
并且当self.__proto.transport.write(data)
被调用时,数据附加到内部缓冲区比发送回客户端更快,因此内存耗尽。当缓冲区达到一定大小时我可以停止读取并在缓冲区全部发送到客户端后恢复读取?或类似的东西?