我试图在python(v3)中发送和接收二进制数据。我试图这样做的方法是在客户端,我手动创建一个字节串,然后通过套接字将其发送到服务器。在服务器端,我接收数据并手动访问各个位以解析消息。
客户端的外观如下:
remoteIP = "164.107.112.72"
remotePort = 34562
remoteStruct = remoteIP.split('.', 4)
remoteIPBytes = ((int)(remoteStruct[0])).to_bytes(1, byteorder='little') + ((int)(remoteStruct[1])).to_bytes(1, byteorder='little') + ((int)(remoteStruct[2])).to_bytes(1, byteorder='little') + ((int)(remoteStruct[3])).to_bytes(1, byteorder='little')
headerStruct = remoteIPBytes + remotePort.to_bytes(2, byteorder='little')
sequenceNum = 0
size = #filesize
data = headerStruct + sequenceNum.to_bytes(1, byteorder='little') + (1).to_bytes(1,byteorder='little') + size.to_bytes(4, byteorder='little')
#data is then sent to server
这是服务器处理数据的方式:
serversock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP Datagram
host = '164.107.112.70'
serversock.bind((host, localPort))
seqNum = 0
#get size
size = 0
var = serversock.recvfrom(12)
seqNum = int.from_bytes((str(var))[6], byteorder='little')
在最后一行代码中,我得到一个错误,说(str(var))被视为unicode字符串而不是二进制字符串。但是,如果我不作为字符串强制转换,我会获得一个超出范围的访问错误。
有人可以向我解释一下在python中发送和接收二进制数据的正确方法是什么?我在发送数据之前/之后尝试使用struct.pack和unpack,但是在解包时我总是遇到错误,即使格式字符串相同
答案 0 :(得分:0)
(int)(remoteStruct[0])
这看起来很像一些C代码。 Python没有像C这样的类型转换器。
int
指的是一个对象。你使用它的方式就是调用它 - 就像它是一个函数一样。
而是写一些像int(remoteStruct[0])
这样的东西。你写的是有效的,因为额外的括号完全是多余的,不会改变含义。不过,这不仅仅是语法上的差异。这是两种语言类型系统的基本区别。
这与你的问题无关。
IPBytes = ((int)(remoteStruct[0])).to_bytes(1, byteorder='little') + ((int)(remoteStruct[1])).to_bytes(1, byteorder='little') + ((int)(remoteStruct[2])).to_bytes(1, byteorder='little') + ((int)(remoteStruct[3])).to_bytes(1, byteorder='little')
这是将IPv4地址打包成四个字节的令人难以置信的详细方法。试试这个:
import socket
print socket.inet_pton(socket.AF_INET, "1.2.3.4")
虽然这与你的问题没有直接关系。
IndexError
问题的来源(我猜你遇到的例外,你说“访问越界错误”这不是Python内置类型中实际存在的东西 - 不是' t释义错误,逐字引用它们很可能在附近的某处:
var = serversock.recvfrom(12)
注意recvfrom的返回值:返回值是一对(字节,地址)。
如果您尝试在6
处为此对象编入索引,那么您肯定会收到IndexError
,是的。
使用str
获取此对的unicode字符串表示形式并不会真正有用 - 尽管它可能会阻止索引操作失败,因为生成的unicode字符串可能足够长。 :)不过,你会得到垃圾。
相反,请尝试索引到您读取的字节:
data, addr = serversock.recvfrom(12)
if len(data) > 6:
seqNum = ord(data[6])
请注意,您确实需要注意长度检查。仅仅因为你将12
传递给recvfrom
并不意味着它返回12个字节。这意味着它返回最多 12个字节。当有人向您发送短数据报时,您不希望程序在未处理的异常中爆炸。