我已经编写了一个新的IRC客户机,我刚刚在其中添加了DCC SEND部分,因此支持该应用程序的两个用户的直接文件传输。没什么,想象一下,我使用irc python库为GUI提供客户机和Django。伟大的miniupnpc lib负责端口转发。然而,当文件被正确地发送/接收时,速度绝对是惊人的:大约20kb/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()
方法。当我增加文件.read(),我明白了结构包错误,因为客户端的块接收确认(也结构包)未被我的发送脚本正确读取:数据不是字节长度8。是不是文件.read必须更改的缓冲区?如果是这样的话,为什么发送方和下载方收到的确认字节不一样?如果没有,我应该在哪里提高上传速度?在
正如我已经怀疑和巴库里所指出的,问题确实存在于
file.read(buffer)
线上。我终于发现了我为什么会出现struct.pack
错误:字节确认被正确地发送回发送方,但有时一些数据包被连接在一起。也就是说,对于接收到的每一个数据包,都会以8字节长的压缩无符号整数的形式向发送方应答一个确认。有时,sock.recv()
读取传入数据的速度不够快,因此,我没有使用长度为8的bytes对象,而是使用了长度为16、24、32、40或更多的bytes对象。这就是为什么我不能用struct.pack("!Q", data)
解包。一旦我弄清楚了,解决方案就很容易找到:我只是从
sock.recv()
读取的数据中读取最后8个字节,而不是读取所有内容。现在它像一个魔咒,上传速度是我的带宽允许的最大理论上传速度!!!在相关问题 更多 >
编程相关推荐