Java 与 C++ 的 socket 通信问题
最近在由于某种原因,来了兴趣,准备做个项目,用 Spring Boot + Netty 写个简单的聊天服务器,其中有一个客户端用 MFC 来写。这里就涉及到 Java 与 C++ 的通信问题。
说这个之前,先来了解一下相关知识:字节序 详细介绍请看 wiki 的介绍《Endianness》(这个链接是英文的,中文的我这里打不开,不知道是不是被墙了)
字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前。
主要有 big-endian 和 little-endian 两种格式,
- big-endian:内存地址从左到右与值由低到高的顺序相对应。
- little-endian:地址低位存储值的低位 ,地址高位存储值的高位。
直观一点,直接上来自 wiki 的图
Java 遵循的是 big-endian,而 C++ 依赖于操作系统环境,大部分操作系统遵循的是 little-endian,Windows 下的是 little-endian。
如果两者之间进行字节流通讯,比如 socket 传输,那么问题就来了!因为大家写内存的方式不同,单字节数据还没问题,但是多字节数据,就会导致乱码或者其他不正确的数据产生。举个例子,一个十进制数字 16909320,二进制表示即为 00000001 00000010 00000100 00001000 Java 和 C++ 的 int 类型占用 4 个字节,32bit,那么这个数字在内存显示的方式为
内存地址 | A | A+1 | A+2 | A+3 |
---|---|---|---|---|
Java(Big-endian) | 00000001 | 00000010 | 00000100 | 00001000 |
C++(Little-endian) | 00001000 | 00000100 | 00000010 | 00000001 |
如果 Java 上数字是正确的,不做任何改变传输到 C++,然后会被解析成 00001000 00000100 00000010 00000001,即数字为 134480385 所以两者直接通信,必须对这方面做处理,无论是在传输前转换还是传输后再解析都可以。 处理的方法很多,其中一种比较简单就是移位,即把字节序调整正确:
1 | public class EndianUtil { |