说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

在java中,写socket通讯是如何读取从C++发过来的一个结构数据?

编辑:说三道四文库 发布时间:2018-04-20 07:11
HTML文档下载 WORD文档下载 PDF文档下载
在发送端的发送的是类似如下一个结构:
struct{
  int id;
  char title[50]
  int type;
};

在java中如何读取类似的结构,并把它构造成一个类似以下的类:
class TestStruct{
  int id;
  String title;
  int type;
};



我们是不是可以换一种形式来发送呢

比如把这个结构转化成xml的形式 ,
用JNI来取得三个成员值。
要看你用的是什么socket类,如果是java.net.Socket的话,就直接从Socket的InputStream读取出数据,例如:

byte[] buf = new byte[58];
socket.getInputStream().read( buf );

TestStruct test = new TestStruct();
test.id = (buf[0]&0xFF) | ((buf[1]&0xFF) << 8) | ((buf[2]&0xFF) << 16) | ((buf[3]&0xFF) << 24);
test.title = new String( buf, 4, 50 ); 
test.type = (buf[54]&0xFF) | ((buf[55]&0xFF) << 8) | ((buf[56]&0xFF) << 16) | ((buf[57]&0xFF) << 24);


什么啊.看了就头大啊.
lutao050306() 
什么啊.看了就头大啊.
---------------------------------------
呵呵,小朋友当然看不懂了!
  
 
> 在java中,写socket通讯是如何读取从C++发过来的一个结构数据?

我觉得,最好换一个视角看待这个问题。写 Java 程序,需要从 socket 里取出一个结构化的数据,不要想着这个数据是谁写进来的,只把它当作字节流看待就好了。这几个字节是什么,接下来的那几个字节是什么……然后把它组装到一个 object 里面去。

同时,在 C++ 那头,也不要简单地 send((void*)&st, sizeof(st)),而是老老实实地把要传送的数据一个一个地发送出去。这样你就能保证发送的每一个字节都在你的控制之下,符合你自己制定的“传输协议”。
按你们这样是比较难实现的.
可以用ASN.1 
直接在不同语言中传送对象 结构数据等了
你给出的两个结构完全不能兼容。

肯定不是用JNI解决问题就是了。
我认同那个没有读过高中的人的建议。但是很好的适应性。

其实让C++照顾一下Java的理解能力比较好,不要搞结构。
然后用Axis就接受,就一马平川了。
> 你给出的两个结构完全不能兼容。

也不能这么说吧。二进制(物理存储)级上的确*不兼容*,但从逻辑上讲,“一个整数/一个字符串/一个整数”,这又可以看作是*兼容*的。

leehq(没有读过高中的人) 的方法思路是对的,但需要 C++ 那边的配合(可能这就是你说的“不要搞结构”),否则的话,通过 socket 传过来的未必是 58 个字节。

顺便提一下,leehq(没有读过高中的人) 老兄的方法中,test.title = new String( buf, 4, 50 ); 有点问题,C++ 中的字符串是 null-terminated,并不一定是 50 个字节长。
maquan('ma:kju) :
顺便提一下,leehq(没有读过高中的人) 老兄的方法中,test.title = new String( buf, 4, 50 ); 有点问题,C++ 中的字符串是 null-terminated,并不一定是 50 个字节长。
-----------------------------------------------------------------
你没看这个结构吗,怎么不是50个字长?
struct{
  int id;
  char title[50]
  int type;
};
对 这样是可以的
大家没有遇到C结构体里面存在int[]德情况吧,想一想遇到这样的情况该如何处理呢?
> 你没看这个结构吗,怎么不是50个字长?
> struct{
>   int id;
>   char title[50]
>   int type;
> };

你误会我的意思了,我不是说这个结构里的字节数。这是一个有 50 字节的 char 数组,在 C/C++ 里能够表示一个不超过 49 字节的字符串。当你在 Java 中创建一个等价的字符串的时候,首先需要判断实际的字符串长度(按照 C/C++ 的语法,也就是 null-terminated),然后再去 new String(),而不应该直接 test.title = new String( buf, 4, 50 );
javaoaout(javaoaout) 
大家没有遇到C结构体里面存在int[]德情况吧,想一想遇到这样的情况该如何处理呢?
--------------------------------------------------------------------------------
要看数组的长度,如果是int[4],那么长度就是4*sizeof(int)。



maquan('ma:kju) 
你误会我的意思了,我不是说这个结构里的字节数。这是一个有 50 字节的 char 数组,在 C/C++ 里能够表示一个不超过 49 字节的字符串。当你在 Java 中创建一个等价的字符串的时候,首先需要判断实际的字符串长度(按照 C/C++ 的语法,也就是 null-terminated),然后再去 new String(),而不应该直接 test.title = new String( buf, 4, 50 );
----------------------------------------------------------------------------------
你说得不错,但我只是简单示范一下而已,具体的实现当然要变通一下了。


 
mark up
不用去理会对方是什么方式产生的该结构,java这边只需要将其理解成输入的数据流即可,在读取的时候按照对方约定的数据格式读取即可。

就好比你读取一个位图文件,你不必去理会这个位图文件是用什么语言写的程序生成的一样,你只需要按照这个位图文件的格式读取就行了,这样的程序你可以用c++写,可以用C#写,也可以用java写。
收获颇丰,多谢了!
建议使用SOAP通讯,这样简单多了
收获颇丰?
你不会结贴吗?
支持用xml
了解每种类型的字节数,高低位,就可以为所欲为了
呵呵
例子 double 
long l;

l = b[0];
l &= 0xff;
l |= ((long) b[1] << 8);
l &= 0xffff;
l |= ((long) b[2] << 16);
l &= 0xffffff;
l |= ((long) b[3] << 24);
l &= 0xffffffffl;
l |= ((long) b[4] << 32);
l &= 0xffffffffffl;

l |= ((long) b[5] << 40);
l &= 0xffffffffffffl;
l |= ((long) b[6] << 48);

l |= ((long) b[7] << 56);
return Double.longBitsToDouble(l);
发一段我的程序和linux下的C通讯的代码,希望对你有所启示.
//发送获取资源列表的命令
            Log.log("\n 开始发送获取资源列表的命令:-----------------\n");
            outData.write(strHead.getBytes());
            outData.writeByte(version);
            outData.writeInt(reverseByte_32(serial));
            outData.writeShort(reverseByte_16(type));
            outData.writeShort(reverseByte_16(sub_type));
            outData.writeInt(reverseByte_32(len));
            outData.writeInt(reverseByte_32(result));
            outData.writeLong(reverseByte_32(timeout));

            //接收返回信息
            Log.log("\n 开始接收~获取资源列表~返回信息:-----------------\n");
            byte head[] = new byte[16];
            inData.read(head);
            String strHead_b = new String(head, "GB2312");

            byte version_b = inData.readByte();
            int serial_b = reverseByte_32(inData.readInt());
            short type_b = reverseByte_16(inData.readShort());
            short sub_type_b = reverseByte_16(inData.readShort());
            int len_b = reverseByte_32(inData.readInt());
            int result_b = reverseByte_32(inData.readInt());

....
.....

=======================================================

//java的16BIT的数据格式转换为C语言的数据格式。
    public static short reverseByte_16(int param) throws Exception {
        String order = SysConfig.loadSysConfig("System.byteOrder");
        if (order.equals("1")) { //高字节序传送数据,无须任何转换
            return (short) param;
        }
        int r1 = param & 0x000000ff;
        r1 <<= 8;
        param >>= 8;
        int r2 = 0x0000ffff & param;
        short result = (short) (r1 | r2);
        return result;
    }

//java的32BIT的数据格式转换为C语言的数据格式。
    public static int reverseByte_32(int param) throws Exception {
        String order = SysConfig.loadSysConfig("System.byteOrder");
        if (order.equals("1")) { //高字节序传送数据,无须任何转换
            return param;
        }
        int r4 = param & 0x000000ff;
        r4 <<= 24;
        int r3 = param & 0x0000ff00;
        r3 <<= 8;
        param >>= 8;
        int r2 = param & 0x0000ff00;
        param >>= 16;
        int r1 = 0x000000ff & param;
        int result = (int) (r4 | r3 | r2 | r1);
        return result;
    }
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘