Python3;发送数据时的速度:IRC协议,DCC文件传输

Python3; Speed when sending data : IRC protocol, DCC file transfer

我已经编写了一个新的 IRC 客户端,我刚刚添加了 DCC SEND 部分,因此支持应用程序的两个用户的直接文件传输。没什么,我正在使用 irc python 库为 GUI 的客户端和 Django 提供支持。伟大的 miniupnpc 库负责端口转发。但是,虽然文件正常 sent/received,但速度绝对是可怕的:大约 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 缓冲区必须更改吗?如果是这样,为什么发送方和下载方接收到的确认字节不同?如果没有,我应该去哪里提高上传速度?

正如我已经怀疑和 Bakuriu 指出的那样,问题确实出在 file.read(buffer) 行。我终于找到了为什么我有 struct.pack 错误:字节确认已正确发送回发件人,但有时几个数据包会连接在一起。也就是说,对于接收到的每个数据包,都会以 8 字节长度的压缩无符号整数形式向发送方答复确认。有时,sock.recv() 读取传入数据的速度不够快,然后我没有长度为 8 的字节对象,而是长度为 16、24、32、40 或更长的字节对象。这就是为什么我不能只用 struct.pack("!Q", data) 解压。一旦我弄清楚了,解决方案就很容易找到了:

def on_dccmsg(self, connection, event):
    data = event.arguments[0][-8:]
    bytesAcknowledged = struct.unpack("!Q", data)[0]

我只是从 sock.recv() 读取的数据中读取了最后 8 个字节,而不是读取所有内容。现在它就像一个魅力,上传速度是我的带宽允许的最大理论上传速度!!!