当前位置:   article > 正文

C/C++ 给 Java 通过Socket传输int问题_c++ socket发送int数据

c++ socket发送int数据

C/C++ 给 Java 通过Socket传输int问题

引言

事情是这样的,朋友有个软件,但它是单机版本,他想实时向服务器传输生成出来的报告,算是服务器那边有个备份。
我先看了一下,软件是C/C++的,CRT也是版本齐全,而且那台电脑也不允许装什么其他环境了,我很自然的就用C/C++写了,而服务端使用JAVA写的,因为服务器那边本来就装了JAVA环境,但没有10以上版本的CRT,所以我就用了2个不同语言写了。

int高低位乱序

网络字节顺序规范大端方式存储,这就指定了发送方接收方必须是大端方式发送接收,但是我们通常在C/C++中并不完全遵守这个规范,很常见,我们只将必要的信息进行大端转换,因为这些信息是由系统处理的,应用层的SOCKET库并不需要我们去校验TCP头和IP头,所以我们通常只使用htons转换端口和inet_ptoninet_addr转换IP地址,但我们从来不转换消息体的存储方式,因为接收时buffer同样是按顺序的。

如果两边同时使用c/c++写,那么不会出现这个问题,因为我们知道存储int的时候是小端存储低位低地址高位高地址,客户端通过socket传输int的时候其实就是从int首字节地址开始传输4个字节,如果同时使用c/c++接收的时候同样是从首字节地址开始,所以不会造成乱序问题。

比如:20 = 0x14
由于是占4个字节高位补0x00,其最终为0x00000014
存储在内存中的格式就是14 00 00 00

java服务端接收后,如果直接用ByteBuffergetInt方法,这个数实际上就是错的,因为ByteBuffergetInt方法默认是大端方式转换,它完全遵循网络字节顺序,这也许是因为Java中的char固定为2字节

解决

byteBuffer.order(ByteOrder.LITTLE_ENDIAN) ;
byteBuffer.getInt();
  • 1
  • 2

或者我们手动转换,我们通过read(bytes,0,4),读取4个byte,然后手动将其低位存储到低地址高位存储到高地址,那么这个int就是对的了。

	private static int bytes2Int(byte[] byteVal) {
		if (byteVal == null || byteVal.length != 4) return 0;
        /* 
        	&0xff 的原因是将它原内容转为int再做位移和或运算
        	强转int由于java没有unsigned,所以byte是带符号位的
        	当单byte>128的时候强转int会出现负数(符号扩展)
        	最好的办法就是&0xff
        */
        return byteVal[0] & 0xff | ((byteVal[1] & 0xff) << 8) | ((byteVal[2] & 0xff) << 16) | ((byteVal[3] & 0xff) << 24);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号