Bittorrent 和套接字:如何处理多条消息?

Bittorrent and sockets: how to handle multiple messages?

我正在 python 中编写一个 bittorrent 客户端,并且一直在使用循环从使用 recv() 的对等套接字不断读取消息。

当我 运行 我的程序时,我在 wireshark 中查看我收到的比特流消息。很容易从消息的前 5 个字节中判断出您得到的是哪种消息,因为长度和消息 ID 已在此处指定。

我 运行 在处理接收包含多条消息的数据时遇到了一些问题。

我尝试通过编写这样的方法来解决它:

    def handleMultiple(self, message, peer):
        total_length = len(message)
        parsed = 0
        while parsed < total_length:
            m_len, m_id = struct.unpack(">IB", message[parsed:parsed + 5])
            m_total = m_len + 4
            print(m_len, total_length, parsed, m_id, peer.made_handshake, peer.ip)

            self.handleMessage(message[parsed:m_total + parsed], peer)
            parsed += m_total

该函数只是将接收到的字节分解为其组成消息,并将其交给知道如何处理各个消息的消息处理程序。

问题是,当我从使用 recv() 收到的消息中打印出长度前缀和消息 ID 时,有时它看起来只是垃圾数字。

这真的是我第一次尝试使用套接字,所以我缺乏直觉,无法知道调用 recv() 时我真正得到了什么。我是否应该只对收到的前 5 个字节的数据调用 receive,然后进行一些检查以确保长度和 ID 有效,然后对消息的其余部分调用 recv()?

我应该如何处理一次传入的多条消息?

编辑: 我想提供一些我看到的结果图片,看看是否有人可以帮助确定我遇到的问题。 这是我收到的比特流消息的图片:

这是相应的日志输出: 这些列应该是消息长度 + 4、总消息长度、消息 ID 和来自发件人的 IP:

正如我所见,第一条消息的长度前缀(一次发送给我的多条消息)完全太大了。我从 95.211.212.26 收到的第五条消息是一个格式正确的位域消息。

我注意到的另一件事是,每条多消息消息的假定消息 ID 为 255。此外,鉴于此给定 torrent 的位域消息的总长度为 126,总长度 (303, 328 , 325) 对于一个位域的消息后跟几个 have 消息来说并不是不可想象的。

好吧,我已经设法弄清楚我哪里出错了。我正在从套接字中读取,假设我的消息会完整存在。实际上,我正在阅读消息的初始片段,稍后我正在阅读消息的中间部分。我看到的 255 个值不是消息 ID,实际上是对等位域 (0xff) 的中间值。

我改变了我的方法,以字节为单位将从套接字读取的数据存储到对等方的消息缓冲区。一旦消息缓冲区至少与预期的有效负载一样长,我就会读取消息并修剪缓冲区以排除我刚刚读取的内容。现在我所有消息的 ID 都符合我的预期。