2013-11-03 76 views
1

我有一个android java应用程序通过套接字发送字节,该套接字连接到在Python中运行服务器的主机。我需要接收这些字节,因为它们是从python套接字发送的。我看到在Python中,'socket.recv'只返回一个字符串。当我从java应用程序发送ASCII字符串时,我能够在python服务器中正确接收数据,但是当我使用java字节发送二进制数据时,我看到收到的数据不相同。我需要在Python中接收原始字节以使协议正常工作。请指向正确的方向。如何从Python中的套接字读取原始字节?

插槽上发送数据的代码片段:

private void sendFrameMessage(byte[] data) { 
     byte[] lengthInfo = new byte[4]; 
     Log.v(TAG, "sendFrameMessage"); 

     for(int i=0; i<data.length; i++) { 
      Log.v(TAG, String.format("data[%d] = %d", i, data[i])); 
     } 

     try { 
      lengthInfo[0] = (byte) data.length; 
      lengthInfo[1] = (byte) (data.length >> 8); 
      lengthInfo[2] = (byte) (data.length >> 16); 
      lengthInfo[3] = (byte) (data.length >> 24); 
      DataOutputStream dos; 
      dos = new DataOutputStream(mSocket.getOutputStream()); 
      dos.write(lengthInfo, 0, 4); 
      dos.write(data, 0, data.length); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

Python代码在接收端

def recvFrameMessage(self, s): 
     recv_count = 4; 
     data = s.recv(recv_count) 
     if data == 0: 
      return None 
     total_rx = len(data) 
     lenInfo = data 
     while total_rx < recv_count: 
      data = s.recv(recv_count - total_rx) 
      if data == 0: 
       return None 
      total_rx += len(data) 
      lenInfo = lenInfo + data 

     recv_count = self.decodeFrameLen(lenInfo) 
     logger.info("length = %d" % recv_count) 

     data = s.recv(recv_count) 
     total_rx = len(data) 
     msg = data 
     while total_rx < recv_count: 
      data = s.recv(recv_count - total_rx) 
      if data == 0: 
       return None    
      total_rx += len(data) 
      msg = msg + data 
     logger.info("msg = " + msg) 
     for i in range(0, len(msg)-1): 
      logger.info("msg[%d] = %s" % (i, msg[i])) 
     return msg 
+2

你能提供一些你的代码吗? –

+0

添加了代码片段 –

回答

1

@SteveP为二进制数据“带有某种结构”提供了很好的观点,但如果这是一个普通的字节流,那么在Python 2中,只需将ord()函数应用于从套接字获得的每个“字符”即可。例如,如果Java端发送一个NULL字节,这将显示在Python的结束作为字符"\x00",然后:

>>> ord("\x00") 
0 

要转换整个字符串s

map(ord, s) 

回报一个相应的8位无符号整数列表。

我假设Python 2在这里。

+0

嗨,感谢msp(ord,s),tim。你摇滚。这正是我所需要的。像魅力一样工作。 –

+0

请注意,在java中,'ints'的表示是2的补码。 –

+0

蟒蛇也​​不一样吗? –

1

读二进制数据是完全可行的,但如果从你的Android应用程序二进制表示什么不同比在Python服务器上的字节表示?从Python文档:

完全可以通过套接字发送二进制数据。主要的 问题是,并非所有机器对二进制数据使用相同的格式。 例如,摩托罗拉芯片将代表一个16位整数,其值为 ,两个十六进制字节为00 01.然而,英特尔和DEC是 字节反转 - 相同1为01 00。 转换16位和32位整数 - ntohl,htonl,ntohs,htons “n”表示网络,“h”表示主机,“s”表示短路,“l”表示长路。在网络订单是主机订单的情况下,这些操作什么也不做,但是机器是字节反转的,这些操作适当地将 左右的字节交换。

没有代码和示例输入/输出,这个问题将很难回答。我认为问题在于代表性是不同的。最可能的问题是Java使用大端,而Python坚持你运行它的任何机器。如果你的服务器使用小端,那么你需要考虑这一点。关于endianness,请参阅此处以获得更全面的解释。

+0

当数据是多字节时,字节顺序才起作用,对吗?我一次发送一个字节,而不是4个字节的字。所以,我假设,我应该按照发送的顺序接收数据。纠正我,如果我错了。顺便说一句,添加了代码片段。 –

+0

@PunitSoni不,请考虑数字10的表示形式。如果您从java发送字节,您将得到以下内容:'10100000','00000000','00000000','00000000'。但让我们假设我们只发送第一个字节:“10100000”。在这里,第一个是最不重要的位,但我们可以很容易地将该位解释为最重要的位,即我们将得到160,而不是10. –

+0

@PunitSoni此外,对于整数,java使用2的补码,即另一件要考虑的事情。 –