1

我有一个 android java 应用程序通过套接字发送字节,该套接字连接到在 Python 中运行服务器的主机。我需要接收这些字节,因为它们是从 python 套接字发送的。我看到在 Python 'socket.recv' 中只返回一个字符串。当我从 java 应用程序发送一个 ASCII 字符串时,我能够在 python 服务器中正确接收数据,但是当我使用 java 字节发送二进制数据时,我看到接收到的数据不一样。我需要在 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
4

2 回答 2

2

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

>>> ord("\x00")
0

要转换整个字符串s

map(ord, s)

返回相应的 8 位无符号整数列表。

我在这里假设 Python 2。

于 2013-11-03T22:21:22.327 回答
1

读取二进制数据是完全可行的,但是如果您的 android 应用程序中的二进制表示与 Python 服务器上的字节表示不同怎么办?来自 Python 文档:

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

如果没有代码和示例输入/输出,这个问题将很难回答。我认为问题在于表示方式不同。最有可能的问题是 Java 使用大端序,而 Python 坚持运行它的任何机器。如果您的服务器使用小端,那么您需要考虑到这一点。有关字节顺序的更详尽解释,请参见此处。

于 2013-11-03T21:33:34.553 回答