2014-03-24 61 views
0

我试图发送和接收Python(v3)中的二进制数据。我试图做的方式是在客户端,我手动创建一个字节的字符串,然后通过套接字发送到服务器。在服务器端,我收到数据并手动访问各个位来解析消息。Python发送/ recv二进制数据

这是客户端的外观:

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并解压前/发送数据后尝试过,但在拆箱时,我总是会出错,即使格式化字符串是相同

回答

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地址为4个字节的难以置信冗长的方式。试试这个:

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]) 

通知你真的需要小心检查长在这里。仅仅因为你通过12recvfrom并不意味着它返回12个字节。这意味着它返回高达 12个字节。您不希望程序在第一次有人向您发送短数据报时发生未处理的异常。