【问题标题】:Python send/ recv binary dataPython 发送/接收二进制数据
【发布时间】:2014-03-24 22:05:47
【问题描述】:

我试图在 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 和解包,但在解包过程中我总是会出错,即使格式字符串相同

【问题讨论】:

    标签: python sockets networking


    【解决方案1】:

    (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 内置类型中实际存在的问题 - 不要解释错误,逐字引用)很可能在附近的某个地方:

    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 个字节。您不希望您的程序在有人第一次向您发送短数据报时因未处理的异常而爆炸。

    【讨论】:

      猜你喜欢
      • 2011-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 2017-10-11
      • 1970-01-01
      • 2011-08-11
      相关资源
      最近更新 更多