2013-11-03 79 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的補碼,即另一件要考慮的事情。 –