网络传输大小端详解(欢迎拍砖)

以前一直对大小端觉得很绕,什么网络传输采用的字节序是大端序,比特序采用小端序;小端序的机器字节序和比特序都是小端的,大端序的机器都是大端的,把人能够绕晕了,还是不是很理解对吧?

有篇博客写的还挺详细的,参考的是linuxjournal上面的一片文章,一时间找不到了,下次补上来。

被绕晕的原因其实是因为没有实作,最有效的方法就是直接搞一台大端序的虚拟机,vmware好像是不行的(欢迎高手拍砖),这里用到的工具是qemu这个虚拟工具,具体怎么架设呢?其实很简单,感谢下面几篇博客的作者。

https://blog.csdn.net/victor1960/article/details/41577903 这篇博客让我知道哪里可以直接下载到工具。

http://weimingtom.iteye.com/blog/903245 这篇博客让我知道怎么配网络和理解怎么开启虚拟机

https://www.howtoforge.com/using-old-debian-versions-in-your-sources.list 这篇博客让我知道怎么搞定开发环境

(我的主机环境是win10系统)首先我们需要下一些东西:

download qcow2:  https://people.debian.org/~aurel32/qemu/ 

qemu exe:  http://qemu.weilnetz.de/

qemu使用的是qemu-w64-setup-20171217.exe这个版本,rc版本我这边跑有bug,没有深究。

qcow2使用的是debian_squeeze_powerpc_standard.qcow2,desktop版本也可以起来,但是莫名的我就是用不了,算了,咱也不折腾了,就用standard的就好了。

东西准备好了,就要配置环境了,主要是要把虚拟机启动起来,并且部署好网络。这里还要下载一个东西openvpn,iteye里面提到的网址应该需要外网才能打开,这里直接提供下载地址,可以用迅雷下载到。

https://swupdate.openvpn.org/community/releases/openvpn-install-2.4.5-I601.exe
安装好之后,修改名字,因为需要访问网络,所以把能上网的网卡开启共享并共享给这个虚拟的网卡,默认会windows会帮你把虚拟网卡的ip设成192.168.137.1, 这样就可以了。

这时候使用qemu来开启虚拟机,命令如下,解释参考iteye上面的说明:

.\qemu-system-ppc.exe  -L . -m 1024  -hda .\debian_squeeze_powerpc_standard.qcow2 -localtime -net nic -net tap,ifname=my-tap

这里使用的powerpc的芯片,这个是大端序的。

等待一段时间,有时候感觉卡在boot那里没反应,别管,一般需要个几分钟才能开起来。

登录使用root,密码root

输入ifconfig命令,应该可以发现虚拟机里面的ip应该配好了,也可以照着iteye里面配一下,但是不要去配192.168.200.*的网段了,要用192.168.137.*网段。也许你会发现可以ping通baidu,但是ping不通主机,鄙视自己一下吧,请检查下主机的防火墙是否关了(^_^!)。

下载的镜像应该是没有配置开发环境的,但是呢,你会发现这个系统太老了,apt-get update,install已经不能用了。可能不经常玩debian的人不是很了解怎么弄,方法如下,把/etc/apt/source.list的修改为下面的内容,主要是把ftp改为archive,加上non-free contrib:

deb http://archive.debian.org/debian/ <version> main non-free contrib
deb-src http://archive.debian.org/debian/ <version> main non-free contrib

deb http://archive.debian.org/debian-security/ <version>/updates main non-free contrib
deb-src http://archive.debian.org/debian-security/ <version>/updates main non-free contrib

然后就可apt-get update和install build-essential了。

开发环境建好了,就能够写程序来验证大小端了。

 

上面是配置大端虚拟机的步骤,下面是重点了,如果你懒得配,那就记住。

233755_yqRd_167289.png

如上图,左边的窗口是大端序(powerpc),右边的窗口是小端序(intel,windows)

代码如下

int _tmain(int argc, _TCHAR* argv[])
{
	float i = 123.56f;
	printf("i:%p %f\n", &i, i);
	unsigned char* pi = (unsigned char*)&i;
	for (int j = 0; j<sizeof(i);j++)
	{
		printf("%p %02X\n", &pi[j], pi[j]);
	}

	union{
		int i;
		char c;
	} ui;
	ui.i = 1;
	printf("ui.c: %d\n", ui.c);

	char ca[6] = "hello";

	for (int j = 0; j < 5; j++)
	{
		printf("%p %c\n", &ca[j], ca[j]);
	}


	return 0;
}

可以看出:

1. 对于字符串,大端和小端都是从低地址开始存起,所以不需要大小端转换

2. 对于占多个字节的变量,无论是整形还是浮点型,int,long,float等,字节顺序是反的,所以需要转换。不知道为什么windows没有提供float等浮点数的转换函数,注意请用内存拷贝方法,千万别直接就long=float,然后用_byteswap_ulong就给转了,也许新手会犯这个错误,因为c++有个内置类型数据隐式转换的问题,float数据给long是会截取整数部分给long,内存的数据完全改变了,这里新手玩家要注意下。

3. union是给一个内存取了多个名字(姑且这么理解),实际上使用的同一个内存,上面的int占4个字节,char占1个字节,注意这里呢,占用少字节的无论在大端序还是小端序都是从低地址开始的。如果ui.i=1,因为大端序把高字节放在低地址,所以c会是0,小端序呢,低字节在低地址,所以会是1,这样就可以用ui.c是不是1来判断大小端了。

4. 这里有一个看不到的东西,比特序,因为计算机存储的最小单位其实是字节,所以其实很难看到比特序,即使你用位与的方式去看bit0到bit7的数据,但我觉得应该都是cpu已经处理好了的,所以bit0~bit7的数值无论大小端得到的结果是一样的。在网络传输过程中,实际上不需要考虑比特序的问题,因为网卡会根据CPU的大端小端,在发送和接收的时候自动转换为正确的比特序(欢迎高手拍砖)。

 

转载于:https://my.oschina.net/ddream/blog/1790120

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值