网络字节序列-大端序和小端序

引子

从《一个http请求进来都经过了什么(2021版)》到《懂得三境界-使用dubbo时请求超过问题》,再到《接下来一段时间会对大家进行网络通信的魔鬼训练-理解socket》和《深入理解MQ生产端的底层通信过程-理解channel》,我的思路是一篇篇的深入网络通信底层。

到了通信底层,必须要了解的一个知识是网络字节序列。这个东东,99%以上的开发中都用不到。but:

首先这个问题比较好理解;第二,要手动处理二进制流的话就不得不考虑,否则可能测试的时候完全没有发现问题,到线上出现诡异事件;第三,这个知识如此之重要,我记得大学的时候课本上也讲过。

字节序列的历史

字节序列分成大端序(big endian或称大尾序)和小端序(little endian或称小尾序)。那为什么大小尾序会称为大小端序呢?

术语“little endian(小端)”和“big endian(大端)”出自Swift的《格列佛游记》(Gulliver's Trabels)一书,其中交战的两个派别无法就应该从哪一端(小端还是大端)打开一个半熟的鸡蛋达成一致。就像鸡蛋的问题一样,选择何种字节顺序没有技术上的理由。

“小”国和“大”国,这两大强国在过去三年一直在苦战。战争开始是由于:我们大家都认为,吃鸡蛋前,原始的方法是打破鸡蛋较大的一端,可是“小”国的祖父小时候吃鸡蛋,一次按古法打鸡蛋是碰巧将一个手指弄破了,因此他的父亲,当时的皇帝,就下了一道敕令,命令全体臣民吃鸡蛋时打破鸡蛋较小的一端,违令者重罚。老百姓们对这项命令极为反感。历史告诉我们,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。这些叛乱大多都是由“大”国的人们煽动起来的。因为叛乱平息后,流亡的人总是逃到“大”国去寻救避难,“大”国的人口就增加了。据估计,先后几次有11000人情愿受死也不肯去打破鸡蛋较小的一端。关于这一争端,曾出版过几百本大部著作,不过大端派的书一直是受禁的,法律也规定该派的任何人不得做官。

Swift是在讽刺英国和法国之间的持续的冲突。Danny Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序,后来这个术语被广泛接纳了。因为产生两种序列的标准和Swift讲的故事如出一辙:几十年前,两强互相看不惯,摩托罗拉(Motorala)使用大端序,英特尔(Intel)使用小端序。

大端序和小序的理解

数值例如0x2266使用两个字节储存:高位字节是0x22,低位字节是0x66。

  • 大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。

  • 小端字节序:低位字节在前,高位字节在后,即以0x6622形式储存。

0x1234567大端字节序和小端字节序的写法如下图:

网络字节序列-大端序和小端序_第1张图片

打个比方:

网络字节序列-大端序和小端序_第2张图片

计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。但是,人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

结论:网络字节序列传输采用大端序。

标准不同引发的问题

2016年我做了一款用于处理图片位置被旋转的方法和工具,并成功申请了专利。起因是这样的:

做过一个项目,有天运营打电话过来说:“有个用户上传了头像到咱们应用上,结果头像是倒置的。”我去后台一看果然是和练倒立一样倒置着脑袋。我们自己测试的时候,从来没有发生这种问题。但是用户所有的声音都是有道理的。当时我们动员了公司所有人用我们的应用看看有没有类似的情况。终于在一个三星的手机上重现了这个问题。

原来照片属性中是存储了旋转信息的,我们之所以看到照片显示的位置都很正确,其实是iphone系统,还有大部分的安卓系统发现图片被旋转了之后都有将图片旋转回来的处理。但是在部分android系统中,却没有做这种处理。

网络字节序列-大端序和小端序_第3张图片

上面两张图片,每张图片被旋转了旋转了8个角度。这里面只有它们的EXIF信息里的orientation值不同。EXIF信息是数码相机的拍摄信息,在压缩文件的格式中只有JPEG格式的储存了这种信息。它可以有1-8的8个值。分别对应于旋转0度,水平翻转,旋转180度,垂直翻转,顺时针90度—+水平翻转,顺时针90度,顺时针90度+垂直翻转,逆时针90度。这时就会发生这种情况。

经过调查发现目前并没有现成的java类库来做这件事情,基本都是从系统层面就解决了这个问题。确实有图片处理的类库,可是添加一个大jar包进来就只为获取图片的旋转信息,jar包可有将近一个MB呢。所以咱们尽量还是自己写工具类来解决问题吧。因为这种解决这种问题不涉及其他的处理,这时只用这样一个针对特定问题的工具类增加了代码的可读性,减少了服务器负担。

实现原理简单可以理解为:存储图片的旋转信息都是放在EXIF信息里。所以只要找到EXIF信息,根据EXIF信息里的旋转方向将图片旋转回来即可。当然实际上各种考虑要复杂的多。

后记

还记得《面试中一个暴露能力等级的问题》那篇文章吗?相信只要在工作中遇到问题仔细思考,不放过,一定能说出让面试官眼前一亮的故事。

你可能感兴趣的:(网络,java,python,人工智能,机器学习)