0

我一直在使用客户端/服务器,其中客户端是用 Java (Android) 编写的,而服务器是用 C++ 编写的。我基本上需要能够将数据集传递给它并让它正确解释该数据。

我用 Python 编写了一个原型,因为我知道它在那里应该是什么样子。使用 struct.pack,它将打包数据,您可以指定它以网络字节顺序(Big Endian)进行。这是我写的原型(这适用于服务器)。

  5 def _BuildPDUToTx(pduObj):
  6     txData = struct.pack('!i i', pduObj.Src.Type, pduObj.Src.Len)           #pduObj.Src.Type: 1
                                            #pduObj.Src.Len: 16
  7     txData += pduObj.Src.Value                          #pduObj.Src.Value: sourceid
  8     txData += struct.pack('!i i', pduObj.Dst.Type, pduObj.Dst.Len)          #pduObj.Dst.Type: 2
                                            #pduObj.Dst.Len: 14
  9     txData += pduObj.Dst.Value                          #pduObj.Dst.Value: destid
 10     txData += struct.pack('!i i i i', pduObj.Metadata.Type, pduObj.Metadata.Len,\   #pduObj.Metadata.Type: 3
 11                             pduObj.Metadata.Status, pduObj.Metadata.Remaining)  #pduObj.Metadata.Len: 16
                                            #pduObj.Metadata.Status: 0
                                            #pduObj.Metadata.Remaining: 0
 12     txData += struct.pack('!i i', pduObj.Msg.Type, pduObj.Msg.Len)          #pduObj.Msg.Type: 6
                                            #pduObj.Msg.Len: 27
 13     txData += pduObj.Msg.Value                          #pduObj.Msg.Value: This is the message
 14     return(txData)

我用一些示例代码运行它(示例值是旁边的注释),如果我在服务器端设置一个原始的 netcat 侦听器(只是为了看看数据是什么样子),我会得到以下信息。

0000000 0000 0100 0000 1000 [6f73 7275 6563 6469] *brackets have "sourceid"
0000010 0000 0200 0000 0e00 [6564 7473 6469] 0000 *brackets have "destid"
0000020 0300 0000 1000 0000 0000 0000 0000 0000
0000030 0600 0000 1b00 [6854 7369 6920 2073 6874 *brackets have "This is the message"
0000040 2065 656d 7373 6761 0065]         

我也尝试过这样做(并使用了与 Python 的 struct.pack? 等效的 Java的建议和使用 Java 的 ByteBuffer 来复制 Python 的 struct.pack)。

我使用了以下代码:

client = new Socket(server, port);
ObjectOutputStream dos = new ObjectOutputStream(new BufferedOutputStream(client.getOutputStream()));
ByteBuffer buffer = ByteBuffer.allocate(1000);
dos.writeInt(Src.Type);         // int value 1
dos.writeInt(Src.Len);          // int value 16
dos.writeUTF(Src.Value);        // String value "sourceid"
dos.writeInt(Dst.Type);         // int value 2
dos.writeInt(Dst.Len);          // int value 14
dos.writeUTF(Dst.Value);        // String value "destid"
dos.writeInt(Metadata.Type);        // int value 3
dos.writeInt(Metadata.Len);     // int value 16
dos.writeInt(Metadata.Status);      // int value 0
dos.writeInt(Metadata.Remaining);   // int value 0
dos.writeInt(Msg.Type);         // int value 6
dos.writeInt(Msg.Len);          // int value 27
dos.writeUTF(Msg.Value);        // String value "this is the message"
dos.flush();

InputStream is = client.getInputStream();
byte[] buf = new byte[Constants.ResponseSize];
is.read(buf, 0, Constants.ResponseSize);

client.close();

但是,我得到以下信息。

0000000 edac 0500 4f77 0000 0100 0000 1000 0800
0000010 [6f73 7275 6563 6469] 0000 0200 0000 0e00 *brackets have "sourceid"
0000020 0600 [6564 7473 6469] 0000 0300 0000 1000 *brackets have "destid"
0000030 0000 0000 0000 0000 0000 0600 0000 1b00
0000040 1300 [6854 7369 6920 2073 6874 2065 656d *brackets have "This is the message"
0000050 7373 6761 0065]                         
0000055

Java 似乎增加了很多额外的东西。就像前两个字节一样,我放入流中的任何内容都没有。接下来是我的值 1(32 位)和 16(接下来的 32 位),但是在“sourceid”之前它有 0800。

Java到底在做什么??我怎样才能让它更像python?

4

1 回答 1

1

使用DataOutputStream,而不是 ObjectOutputStream。

ObjectOutputStream 用于将 Java 对象从一个 JVM 传送到另一个 JVM,主要由 java 对象序列化框架使用。

DataOutputStream 以 Big Endian 写入所有内容。

但是,您可能必须小心使用writeUTF. 按照规范,它预先设置了字节序列的长度。这可能是您想要的,也可能不是。

于 2013-08-21T20:46:58.930 回答