网络传输结构体大小端问题

windowsXppppppp 2019-07-10 02:35:52
各位大大 现在我想和c#客户端进行网络传输一个结构体 目前我后台服务器不确定是大端小端 请问应该怎么传输呢?。。。
现在有一些疑惑。。
我这个结构体里有很多结构体 里面的成员有char[]数组 有unsigned int等
char数组不需要转换的对吧?
我从客户端拿过来的数据 分别把成员中的unsigned int 转大小端就好了嘛?
望解答 谢谢~~
...全文
1906 40 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
叫我官人、 2019-07-13
  • 打赏
  • 举报
回复
引用 楼主 LUBILanna的回复:
各位大大 现在我想和c#客户端进行网络传输一个结构体 目前我后台服务器不确定是大端小端 请问应该怎么传输呢?。。。
现在有一些疑惑。。
我这个结构体里有很多结构体 里面的成员有char[]数组 有unsigned int等
char数组不需要转换的对吧?
我从客户端拿过来的数据 分别把成员中的unsigned int 转大小端就好了嘛?
望解答 谢谢~~
一般都是穿base64
guishuanglin 2019-07-12
  • 打赏
  • 举报
回复
传输还要注意的是, 上面说了大小端只是在多字节的数值中, 如果几个多字节的数值排一起怎么传送? 如下:

float f2 = 999.123F;
        	float f3 = 999.567F;
        	//结果:1148831711
        	int i2 = Float.floatToIntBits(f2);
        	int i3 = Float.floatToIntBits(f3);
        	//int是4字节存储, 大端模式顺序处理
        	byte[] byteBuf2 = StaticConvert.intToByte4B(i2);
        	//int是4字节存储, 大端模式顺序处理
        	byte[] byteBuf3 = StaticConvert.intToByte4B(i3);
        	//f2大端结果: 44 79 C7 DF
        	hex2 =   StaticConvert.parseByte2HexStr(byteBuf2, 4);
        	//f3大端结果: 44 79 E4 4A
        	hexStr = StaticConvert.parseByte2HexStr(byteBuf3, 4);
        	System.out.println(" 转成int: "+ i2);
        	System.out.println(" 16进制: "+ hex2);
        	System.out.println(" 16进制: "+ hexStr);
规约上要求 f2在前面则这样送: 44 79 C7 DF 44 79 E4 4A 规约上要求 f2在前后则这样送: 44 79 E4 4A 44 79 C7 DF 多个数据之前的顺序按规约的排列来处理, 单个数值是多字节时内部按大小端规定处理.
guishuanglin 2019-07-12
  • 打赏
  • 举报
回复
提示, byte转成 16进制, 就是为了方便打印查看 byte中的值, 在网络转输时还是用byte传输. 为什么选择 16进制来显示? 是因为1个字节是8位二进制, 把1个字节拆成两半, 一半是4位二进制, 4位二进制刚好表示16 (0-15), 每一半正好用一个16进制字符显示. 这样一来, 打印和显示时, 不管数值是 1还是 100 他的16进制总是 2个字符, 非常有规律, 非常方便查看.
guishuanglin 2019-07-12
  • 打赏
  • 举报
回复
1,首先知道通信规约, 比如 104 规约, 645规约之类. 这里面有规定是用大端,还是用小端 2, 规约统一了, 不管用什么语言开发都没有问题, 如果用java非常好做: java统一是大端, 知道了源头就可以传换成规约要的顺序. C#不记得是什么顺序, 但肯定是固定的, 可以转换成规约指定的顺序. 3,接收端也按规约开发, 用指定顺序接收. 4,约定编码字符类型(GBK,UTF8), 约定数字类型字节长度,比如float, int可以统一用 4字节传输, (float转成4字节整数,参考IEEE的标准,java中Float本身有方法直接可以转) 如果用C ++这种类型长度不固定的, 想法办找个有固定长度的类型, int,String之类. 然后把 float, int, 中文, 英文统统转成 byte, 然后把 btye 转成16进制字符串, 一个byte转成 2个字符, 比如 btye a = 104, 转成16进制就是2个字符 68 字节顺序说明: 字节顺序只是针对于有多个字节的数值, 如果是单字节则没有顺序的说法. 比如:

float f2 = 999.123F;
 //结果:1148831711
int i2 = Float.floatToIntBits(f2);
        	//int是4字节存储, 大端模式顺序处理
        	byte[] byteBuf2 = StaticConvert.intToByte4B(i2);
        	//int是4字节存储, 小端模式顺序处理
        	byte[] byteBuf3 = StaticConvert.intToByte4L(i2);
        	//大端结果: 44 79 C7 DF
        	hex2 =   StaticConvert.parseByte2HexStr(byteBuf2, 4);
        	//小端结果: DF C7 79 44
        	hexStr = StaticConvert.parseByte2HexStr(byteBuf3, 4);
        	System.out.println(" 转成int: "+ i2);
        	System.out.println(" 16进制: "+ hex2);
        	System.out.println(" 16进制: "+ hexStr);
int 在java中是 4字节, 转成16进制正好是 4*2 =8字符, 每2个字节是 1字节, 大小端处理后的串是相反的. 如果值是一个字节 就没有大小端之分的, 只有多字节的值才区分大小端.
Acuity. 2019-07-12
  • 打赏
  • 举报
回复
网络传输都是大端模式。网络间传输用json啊,不要穿结构体。
Mͯcu@ 2019-07-12
  • 打赏
  • 举报
回复
闲来无事看看
windowsXppppppp 2019-07-12
  • 打赏
  • 举报
回复
引用 37 楼 guishuanglin 的回复:
传输还要注意的是, 上面说了大小端只是在多字节的数值中, 如果几个多字节的数值排一起怎么传送? 如下:

float f2 = 999.123F;
        	float f3 = 999.567F;
        	//结果:1148831711
        	int i2 = Float.floatToIntBits(f2);
        	int i3 = Float.floatToIntBits(f3);
        	//int是4字节存储, 大端模式顺序处理
        	byte[] byteBuf2 = StaticConvert.intToByte4B(i2);
        	//int是4字节存储, 大端模式顺序处理
        	byte[] byteBuf3 = StaticConvert.intToByte4B(i3);
        	//f2大端结果: 44 79 C7 DF
        	hex2 =   StaticConvert.parseByte2HexStr(byteBuf2, 4);
        	//f3大端结果: 44 79 E4 4A
        	hexStr = StaticConvert.parseByte2HexStr(byteBuf3, 4);
        	System.out.println(" 转成int: "+ i2);
        	System.out.println(" 16进制: "+ hex2);
        	System.out.println(" 16进制: "+ hexStr);
规约上要求 f2在前面则这样送: 44 79 C7 DF 44 79 E4 4A 规约上要求 f2在前后则这样送: 44 79 E4 4A 44 79 C7 DF 多个数据之前的顺序按规约的排列来处理, 单个数值是多字节时内部按大小端规定处理.
大神 我好好消化一下 谢谢
windowsXppppppp 2019-07-12
  • 打赏
  • 举报
回复
引用 31 楼 熊猫党团委副书记 的回复:
TLV
都是大神呀 好多我都不了解 谢谢
引用 33 楼 一只巴扎黑 的回复:
你需要将整个结构体数据转换为网路字节序。网络字节序是大端字节序,即最高有效字节在最前面,目前(Intel)X86系CPU是小端字节序,所以在X86上开发的网络程序在进行网络通信时要进行字节顺序转换。 大多数CPU可以配置自身为小端方式或大端方式。
感谢感谢!
neo_liang 2019-07-11
  • 打赏
  • 举报
回复
网络上传输整数 建议是小端,可以在客户端和服务端自己判断然后转换下。当然如果客户端和服务端沟通好了,传输大小端都可以 只要保证两边做相应的转换就可以
windowsXppppppp 2019-07-11
  • 打赏
  • 举报
回复
引用 25 楼 neo_liang 的回复:
网络上传输整数 建议是小端,可以在客户端和服务端自己判断然后转换下。当然如果客户端和服务端沟通好了,传输大小端都可以 只要保证两边做相应的转换就可以
看来还是要协议制定规范好才行~

引用 26 楼 nice_cxf 的回复:
大小端取决于CPU,当然有的CPU版本LINUX内核可以指定大小端,inter的CPU都是小端的,跟操作系统无关
在大端的系统中,htonl是无效的
通讯协议里面,一般规定是网络序还是主机序,网络序就是大端,主机序是要看你机器的大小端,一般来说,为了保持兼容性,网络通讯都是应该用网络序来传输,所以发送端要用htonl等函数转成网络序,接收端用ntohl等函数转换成主机序
如果你能确定所有通讯的机器大小端完全相同,可以用主机序传输,这样两边都不用做转换
谢谢 那我了解了 ~
windowsXppppppp 2019-07-11
  • 打赏
  • 举报
回复
引用 25 楼 neo_liang 的回复:
网络上传输整数 建议是小端,可以在客户端和服务端自己判断然后转换下。当然如果客户端和服务端沟通好了,传输大小端都可以 只要保证两边做相应的转换就可以
看来还是要协议制定规范好才行~
windowsXppppppp 2019-07-11
  • 打赏
  • 举报
回复
引用 24 楼 SoUIcoder 的回复:
序列化了解下
嗯嗯! 我比较菜 去学习一下
nice_cxf 2019-07-11
  • 打赏
  • 举报
回复
大小端取决于CPU,当然有的CPU版本LINUX内核可以指定大小端,inter的CPU都是小端的,跟操作系统无关 在大端的系统中,htonl是无效的 通讯协议里面,一般规定是网络序还是主机序,网络序就是大端,主机序是要看你机器的大小端,一般来说,为了保持兼容性,网络通讯都是应该用网络序来传输,所以发送端要用htonl等函数转成网络序,接收端用ntohl等函数转换成主机序 如果你能确定所有通讯的机器大小端完全相同,可以用主机序传输,这样两边都不用做转换
qq_44815533 2019-07-11
  • 打赏
  • 举报
回复
引用 11 楼 lin5161678 的回复:
也可以传递一个 int类型1
服务端看到这个字段是1 表示不需要调整端序
服务端看到这个字段不是1 表示需要调整端序

不是说程序员最简单直接吗?为什么有技术问题咨询,跟了这么多帖子,也没人加我呢?想开发一款智能扫描分类箱,有没有懂的啊,加我986367870 不加后悔
  • 打赏
  • 举报
回复
你需要将整个结构体数据转换为网路字节序。网络字节序是大端字节序,即最高有效字节在最前面,目前(Intel)X86系CPU是小端字节序,所以在X86上开发的网络程序在进行网络通信时要进行字节顺序转换。

大多数CPU可以配置自身为小端方式或大端方式。
windowsXppppppp 2019-07-11
  • 打赏
  • 举报
回复
引用 31 楼 熊猫党团委副书记 的回复:
TLV
都是大神呀 好多我都不了解 谢谢
这不是鸭头 2019-07-11
  • 打赏
  • 举报
回复
TLV
搬砖道人 2019-07-10
  • 打赏
  • 举报
回复
序列化了解下
windowsXppppppp 2019-07-10
  • 打赏
  • 举报
回复
引用 20 楼 zjq9931 的回复:
协议啊,要一致。
是的是的 谢谢
windowsXppppppp 2019-07-10
  • 打赏
  • 举报
回复
引用 19 楼 smwhotjay 的回复:
如果是和其他语言通信。结构体就不适合了。字节对齐和大小端都是问题。考虑用xml或者json文本格式更好。 但是结构体非要用,也不无可,只是容易出小bug,但要懂。我和java通信结构体没问题。使用32位的即4字节的int,字符串要固定长度。java对应接收4字节转int,接收固定长度byte的字符串。
是的 确实有这种问题 在客户端正常的字节长度 在我这就被补齐多了几个字节了 天坑啊~~
加载更多回复(21)

65,189

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧