我已经编写了一个新的IRC客户端,我刚刚添加了DCC SEND部分,因此支持应用程序用户的直接文件传输。没什么,很奇怪,我正在使用irc python库为客户端和Django提供GUI。伟大的miniupnpc lib负责端口转发。但是,在正确发送/接收文件的同时,速度绝对是可怕的:大约20 KB / s。为了测试服务器,我使用Hexchat发送了一个包:上传速度是最大理论带宽速度(换句话说,优秀)。我试着找一些我可能错过的缓冲区。最后,我必须说我完全不知道为什么我的上传速度如此糟糕,需要一些洞察力。这是我上传脚本的相关部分。
def on_dcc_connect(self, c, e):
t = threading.Timer(0, upload_monitoring, [self, c])
t.start()
log("connection made with %s" % self.nickname).write()
self.file = open(self.filename, 'rb')
self.sendBlock()
def sendBlock(self):
if self.position > 0:
self.file.seek(self.position)
block = self.file.read(1024)
if block:
self.dcc.send_bytes(block)
self.bytesSent = self.bytesSent + len(block)
else:
# Nothing more to send, transfer complete.
self.connection.quit()
def on_dccsend(self, c, e):
if e.arguments[1].split(" ", 1)[0] == "RESUME":
self.position = int(e.arguments[1].split(" ")[3])
c.ctcp("DCC", self.nickname, "ACCEPT %s %d %d" % (
os.path.basename(self.filename),
self.eport,
self.position))
def on_dccmsg(self, connection, event):
data = event.arguments[0]
bytesAcknowledged = struct.unpack("!Q", data)[0]
if bytesAcknowledged < self.bytesSent:
return
elif bytesAcknowledged > self.bytesSent:
self.connection.quit()
return
self.sendBlock()
send_bytes(block)
方法是基本的socket.send()
方法。当我增加file.read()的缓冲区时,我得到struct.pack错误,因为我的发送脚本没有正确读取客户端的块接收确认(也是struct.pack):数据不是字节长度8.是不是file.read缓冲区必须更改?如果是这样,为什么收到的字节确认在发件人方面与下载方不一样?如果没有,我应该在哪里提高上传速度?
答案 0 :(得分:0)
正如我已经怀疑的那样,正如Bakuriu指出的那样,问题确实存在于file.read(buffer)
行。我终于找到了为什么我有struct.pack
错误:字节确认已正确发送回发件人,但有时一些数据包连接在一起。也就是说,对于接收到的每个分组,以8字节长度打包的无符号整数的形式向发送方应答确认。有时,sock.recv()
没有足够快地读取传入数据,然后,我有一个长度为16,24,32,40或更长的字节对象,而不是长度为8的字节对象。这就是为什么我不能用struct.pack("!Q", data)
打开包装的原因。一旦我弄明白,解决方案很容易找到:
def on_dccmsg(self, connection, event):
data = event.arguments[0][-8:]
bytesAcknowledged = struct.unpack("!Q", data)[0]
我刚从sock.recv()
读取的数据中读取最后8个字节,而不是读取所有内容。现在它就像一个魅力,上传速度是我的带宽允许的最大理论上传速度!!!