我正在编写一个程序,用于使用Python的两个机器人之间的通信,如果有人知道的话,可以使用天网项目。在写作的时候,我遇到了这个问题
File "C:\Users\achau\Desktop\Uni\Fundamental of Sec\Project\part1\skynet_intro\lib\comms.py", line 87, in recv
unpacked_contents = struct.unpack('H', pkt_len_packed)
struct.error: unpack requires a bytes object of length 2
奇怪的是代码总是在第一次工作,但第二次输入消息时,它就变成了那样。有谁有想法吗?这是代码行
def recv(self):
# Decode the data's length from an unsigned two byte int ('H')
pkt_len_packed = self.conn.recv(struct.calcsize('H'))
unpacked_contents = struct.unpack('H', pkt_len_packed)
pkt_len = unpacked_contents[0]
答案 0 :(得分:0)
我认为你的conn
是一个套接字。 socket.recv(n)
返回最多n个字节,但不保证有n个字节。只是一个猜测,但可能是你的recv只返回一个字节。
在调用pkt_len_packed
之前检查struct.unpack()
的长度是多少。它可能只是一个。
一个非常典型的套接字编程错误是套接字传递消息的假设。他们没有,他们提供数据,并且完全不了解其格式,长度,内容和其他类似的东西。如果您正在接收消息,则需要解析数据流中的消息。如果你打算发送2个字节,那么当你调用recv()时,完全有可能只传输了一个字节,你就会收到它。然后你需要存储你刚收到的东西并继续接收,直到你拥有你需要的一切。如果您的套接字已经包含多条消息,并且您调用的recv的长度大于队列中第一个消息的长度,那么您也将从一个或多个连续消息中接收数据。如果您现在丢弃此数据,则会丢失消息或部分消息,或两者都丢失。
另一种可能性是您传输N个字符,但是有一个尾随换行符或另一个终止符。例如,如果您构建了一个首先传输数据长度然后传输实际消息的消息传递协议,但是您向套接字写入长度和带有尾随字符的消息字符串,那么您的接收器将与您的第一条消息一起正常工作。它将获得长度,在该长度上调用recv()
,你会认为一切都很好。但是还有一个字节要从套接字中读取(换行符?,终止为零?),当你现在尝试再次调用recv()
以获得第二条消息的两个字节长的消息长度时,你实际上是刚收到你应该读作第一条消息的一部分的尾随终结符字符,或者根本不发送。这只是猜测,但这些错误非常普遍。
这就是为什么你应该使用更高级别的操作消息的接口(ZeroMQ会这样做),或者从消息处理中分离套接字操作,并在对它做任何事情之前验证从套接字接收的所有内容,以确保你拥有您需要的所有数据。您还需要知道您实际写入套接字的内容,并确保您收到所有不可见的字符。如果您收到的数量超过了预期收到的数量,则需要保留剩余部分并继续累加,直到出现完整的消息。