今天我在QQ上和一位小黄鸭问好,鸭兄也十分友好的对我进行了回复。这让我不禁好奇,我在成都敲打下的“hello”,是如何通过我们现在的无线网络传输到远在河南度♂假的鸭兄那边呢?对此笔者作了一系列的调查,最终本文从字符串“hello”的角度,对这一问题进行阐述。
本文拟从以下几个方面解答该问题:
一、hello去哪了
二、IEEE 802协议体系
三、无线局域网协议802.11
四、总结
相信有人会问,802.11协议只是很多通信协议的一种。并且互联网协议还有很多,比如TCP/IP的协议,作者为什么不说呢?那是因为:
一、hello去哪了
1.1 编码方式
在电脑眼里,任何类型的数据,都是01的二进制数字。大小写英文字符、阿拉伯数字以及一些常 用的标点、运算符号等都使用以8位二进制数为基础的ASCII码表示。以“hello”为例,它总共有5个字母,则需要40位二进制数字:
01101000 01100101 01101100 01101100 01101111
勤劳的作者还从网上截了ASCII码的图。值得注意的是,上表中01二进制用16进制来表示了。这是一个很讨巧的做法,因为1位十六进制的数(0~9,A,B,C,D,E,F)恰好可以使用4位二进制表达,极大的减少了表示的繁琐程度。
另外,为了能够表示其他比如中国,日本的文字和“♂”符号,机智的美国人提出了一套称为Unicode的标准方案,使用16位的二进制数字,囊括了世界上几乎所有的文字。我们常见的utf-8编码模式,就是来源于此。
计算机以一个8位二进制数为单位计算内存,单位的名称为“Byte”。事实上,“hello”字符串只是一个体量很小的数据。“hello”只占据5 Byte的数据,而我与小黄鸭的对话截图,占据8045 Byte的内存。B站上的视频“更衣室的对决”,有32.9MB即32900000 Byte的内存。这些数据,或大或小,都是在遵守了互联网协议的情况下,通过互联网,进入我的手机。
1.2 数据的封装
光光编码一段“hello”是无法发送给小黄鸭的。电脑还需要知道发送者(我的QQ账号),发送时间,和发送对象(小黄鸭的QQ账号)等。封装好之后的数据hello2.0(这么说是不严谨的,然而我不是QQ的程序员,只能瞎JB乱猜了),便整装待发,准备发送到腾讯的服务器。同时QQ程序告诉操作系统,需要发送hello2.0到腾讯服务器。
我电脑的操作系统立刻查询自己所在的局域网,找到路由器的ip地址。然后在hello2.0数据上加入了自己的MAC地址,腾讯的地址以及其他一些控制信息网络信息,将hello3.0发送给路由器。路由器经过网关,将hello3.0发送到腾讯服务器。
由于我在登录QQ的时候,已经实现ping过腾讯的服务器,知道到达腾讯服务器的路由路线是怎么样的,所以按照这个路线,我的hello3.0就可以直接发送到腾讯服务器了。腾讯服务器经过重重解码,发现这条消息的内容是我对小黄鸭说“hello”,于是又将这个消息发送给小黄鸭。
腾讯的QQ服务器众多,上图只是选择一个随便百度到的地址219.133.49.171。感兴趣的读者可以使用管理员权限打开cmd窗口,输入tracert 219.133.49.171,看看运行结果和我的是不是一样的。
第一列表示路由的次数,在每次路由时,都会发出3个TTL包,所以第二、三、四列表示的都是到达这个路由的时间,3个时间会由于网络波动而有一定偏差,但是大体上量级不变。第五列表示到达的ip地址,其中,192.168.0.1,192.168.1.1是本地局域网的地址,笔者猜测192.168.0.1是路由器接收笔记本电脑信号的地址,192.168.1.1是局域网内另外一个设备(或者网关)。100.64.0.1是神秘的保留地址。 182.150.19.165是四川省成都市的地址,171.208.199.81是四川省遂宁市的,202.97.29.41是北京市的,119.147.220.78,14.17.0.18, 14.17.2.138是广东省深圳市的地址,219.133.49.171是广东省深圳市宝安区的。
综上所述,我发送的hello消息,从成都出发,经过遂宁,北京,最后到达深圳,直至深圳市宝安区的腾讯服务器,走的还是挺远的吼。
1.3 网络模型
上述发送hello的过程,在计算机工程中,可以使用OSI七层模型表示(TCP/IP使用的是五层模型,实际上它将OSI最上面3层合并成了一层名为“应用层”),如下图所示。
思考题:这些由大写英文表示的协议分别有什么作用
在应用层中,我登录QQ使用了TCP和HTTP协议。在表示层中我对hello字符串进行编码封装形成hello2.0。接着操作系统会在会话层激活发送函数,同时生成hello3.0。然后在传输层,我的hello3.0通过UDP协议(高贵的QQ会员则使用了TCP协议)将数据发送出去。值得一提的是,我们的数据要从笔记本电脑先经过链路层和物理层通过无线电波传送至路由器,然后再经过数据链路层到达位于网络层的路由器,接着才能在网络中遨游。
再来回顾先前我给小黄鸭发送消息的过程,首先我在应用层封装了hello字符串,加上了发送者和接收者。接下来在传输层我加上了TCP协议的内容,网络层我加上了IP协议的内容,接下来我在数据链路层加上了以太网的内容。最终我的hello字符串穿上了一层又一层的马甲,开始在互联网上流通。
值得一提的是,以太网作用于指有线的通信,即通过网线或者光纤传播。然而,很多情况下笔记本电脑都是通过WiFi连接到路由器,而WiFi使用的并非以太网协议,而是802.11协议。
二、IEEE 802协议体系
首先有一个问题,为什么要协议?为什么不可以直接把一个字符串发出去,却非要这么繁琐的加上这么多首部?计算机的协议可以和人类社会中的法律作类比,两者的目标都是为了让整个系统有序而高效的运行。如果没有TCP协议,就无法确认数据被正确的送达,如果没有IP协议,数据就无法知道即将去哪里,如果没有以太网协议,多个设备的数据传输可能就会发生冲突。换句话说,协议不仅不是来阻碍系统的,恰恰相反,协议服务于系统,促进系统的健康,有效,高效,稳定的运行的。
802系列协议,专门用于局域网标准。著名的802.11,802.3等协议,均出于此。下图是该协议族的主要分布。802.1负责定义局域网的体系,结构。802.2负责定义逻辑链路子层(LLC)。802.3是以太网介质访问控制协议。802.5规定了令牌环网的介质访问控制规范。802.11规定了无线局域网的介质访问控制协议及物理层技术规范。
和其他协议一样, 正是由802协议族的一系列的规定,我们的网络世界和通信世界才变得有序,高效。每个人才得以高速的访问网络资源而不发生冲突。
三、无线局域网协议802.11
IEEE协会于1997年推出第一个版本的802.11协议。稍有无线电基础的人都知道,电磁波有不同的频率,同时在通信领域有不同的调制方式,单一的协议无法覆盖所有的频段和所有的调制方式。同时通信速率的大小与通信质量,硬件设施等是一个权衡,所以于是随着技术的进步和硬件设备的不断发展,IEEE之后又陆续推出了802.11a,802.11b等一系列协议,规定了通信速率,适用于不同的频段和调制方式等。
这里有必要澄清一下WiFi与802.11协议的关系。1999年工业界成立了WiFi联盟,致力于解决符合802.11标准产品的生产和维护问题。从这个角度上讲,WiFi是一个组织,而不是一个信号。自成立以后,WiFi组织制定了一系列的802.11标准,例如802.11g,802.11e,802.11f,802.11n等。我们日常使用的路由器也好,手机上的“WiFi”信号也好,都只是是遵循了802.11协议族的电磁波信号而已。
3.1 802.11协议特色
如下图所示,hello字符串从作为终端的笔记本电脑传送到路由器。由于笔记本电脑和路由器之间没有网线连接,所以原本的以太网协议802.3无法使用,只能使用802.11的无线网协议。由于有线通信和无线通信的区别,相比于以太网,802.11协议有如下特征。
冲突检测 CSMA/CA
在以太网协议中,冲突检测就已经存在了。其名称为CSMA/CD(Carrier Sense Multiple Access/Collision Detection),它的作用是为了防止有线通信中的信号冲突;在无线情况下,冲突的检测存在“Near/Far”现象。这是由于要检测冲突,设备必须能够一边接收数据信号,一边传输数据信号,而这在无线系统中是办不到的。于是802.11协议就对CSMA/DA作了一些调整,采用了新的协议CSMA/CA(Carrier Sense Multiple Access/Collision Avoidance)或者DCF(Distributed Coordination Function)。
首先需要解释一下为什么会冲突。信息想要完整的从一端传达到另一端,需要信号有良好的信噪比。通常信噪比要保证信息的功率是噪声的10倍以上(实际的工程中信噪比使用db作为单位)。假设我和小黄鸭都想把自己的信息(分别为hello和fa♂q)发送给小灰猫。可是当小灰猫想听明白我发送了什么时,小黄鸭的信息就成了噪声;当小灰猫想听清小黄鸭说了什么时,我的信息就成了噪声。当我和小黄鸭发送信号的功率相等时,则无论哪种情况,信噪比都是1。
CSMA/CD工作的基本原则是:发送数据前,先侦听信道是否空闲,若空闲,则立即发送数据。若信道忙碌,则等待一段时间至信道中的信息传输结束后再发送数据。若在上一段信息发送完毕后,同时有2个以上的节点提出发送请求,则判定为冲突。若侦听到冲突,则立即停止发送数据,等待一段随机时间,再重新尝试。当重新尝试超过了一定的次数后,该节点就会放弃发送数据。
总的原则是:先听后发,边发边听,冲突停发,随机延迟后重新发。
如上图所示,在T1时刻,我率先发送了hello。在T2时刻,当我还在发送hello时,小黄鸭也想发信息,可是他检测到了我正在发送hello,所以他先等待,暂不发送。T3时刻,当小黄鸭要发送消息时,正巧有个小灰猫也想发送消息,则双方都检测出了冲突,于是都选择暂不发送。等待一段随机时间后,比如像上图那样,小黄鸭的等待时间正好小于小灰猫的等待时间,于是小黄鸭就可以先于小灰猫发送消息。
可以发现,想要实现上述的功能,不论是我,小黄鸭,还是小灰猫,都不得不在发送时还具备侦听功能,而这在无线设备中是很难实现的。CSMA/CA使用了ACK(Acknowlege)信号来保证数据的有效传输。同时在发送之前,默认可能会和别的节点冲突,所以一开始就增加一个随机等待时间。
如上图所示,我想发送hello时,必须先等待一段时间。小黄鸭收到hello消息后,会向我发送一个ACK信号以让我确认,我已经成功的发送了消息。但是,这一切的前提是小灰猫不说话。如果在小黄鸭接收我的消息时,小灰猫也给小黄鸭发送消息,那么小黄鸭就无法接收到我的hello消息,它也不会发送ACK给我。当我在一定时间内没有接收到ACK消息后,我就会重新发送hello消息。
不难发现,当小灰猫非常频繁的向小黄鸭发送消息时,我发送消息的效率就会非常低。这是因为,我没有意识到还有一只小灰猫在和小黄鸭说话。换句话说,小灰猫对我而言是“隐藏”的,这就涉及到了“隐藏节点”的问题(hidden node)。在802.11协议中,有一个专门的RTS/CTS选项(Ready To Send/Clear To Send),用来处理这种问题。
“隐藏结点”问题
如上图所示,蓝色的圈表示我的信号可以传播的距离,红色的圈圈表示小黄鸭的信号可以传播的距离。显然,小黄鸭既可以接收我的信息,也可以接收小灰猫的信息。而我由于只能接收到小黄鸭的信息,所以小灰猫对我来说是“隐藏”的。
这时我向小黄鸭发送了RTS信号,告诉小黄鸭,我要向他发送数据。小黄鸭接收到了我的RTS信号后,如果它同意了我的发送请求,就会向我发送一个CTS信号,告诉我可以发送数据,同样在通信范围的小灰猫听见了这个CTS信号,就会暂停向小黄鸭发送数据。之后我就开始发送数据。当小黄鸭接收完我发送的数据之后,就会向先前一样,向我发送一个ACK信号,告诉我我已经成功的发送了数据。同时小灰猫接收到了ACK之后,又获得了发送数据的权力。
为了方便起见,在上图中省略了等待一段随机时间的表示。RTS信号有点像把有用的信道“预约”了一样。虽然RTS/CTS信号占据一定的发送间隔,但是由于它们相比于数据包来讲,封包很小(RTS/CTS分别为20字节和14字节,数据包可以到达2346个字节),所以对整个通信系统的性能影响也不是很大。
值得注意的是,这和TCP/IP中的三次握手协议是两码事。
数据校验
在802.11协议中,每一个在无线网络中传输的数据包都被附加上了校验位以保证它在传送的时候没有出现错误,这和以太网中通过上层TCP/IP协议来对数据进行校验有所不同。
包分片/组装
包分片的功能允许大的数据包在传送的时候被分成较小的部分分批传送。这在网络十分拥挤或者存在干扰的情况下(大数据包在这种情况下传送非常容易遭到破坏)是一个非常有用的特性。这项技术大大减少了许多情况下数据被重传的概率,从而提高了无线网络的整体性能。
MAC子层负责将收到的被分片的大数据包进行重新组装,对于上层协议来讲,这个分片的过程是完全透明的。
3.2 数据的发送
当走出网卡到达数据链路层时,原本的以太网协议(通过数据包中的以太网首部和以太网尾部体现)无法在无线传输时使用,所以会有专门的硬件设备将数据转换成802.11格式。
如上图所示,当硬件设备接收到来自上层的以太网数据包时,会根据该数据包的内容,为其加上802.11格式的协议头。同时,由于需要依赖于逻辑链路层协议,所以还要为其添加逻辑链路层协议头SNAP。接着确定是否使用RTS/CTS以及是否需要加密和分片。最终,将数据包放入缓存内,等待驱动程序去发送。
3.3 数据的接收
数据的接收是发送的逆向行为,如下图所示。首先接收硬件会不断统计环境中的无线信号强度,从而判断当前无线网络的质量。当硬件接收到数据帧时,会从802.11协议头中提取该数据包的类型,分片,加密等信息。同时将数据写入缓存,接收下一个数据包以便对分片的信息进行重组。最后,将完整的数据包封装成以太网的形式交至上层网络。
四、总结
当我们在网路上和别人闲聊的背后,实际上涉及了大量的基础设施和算法。一串文本,远远没有一串文本这么简单。幸运的是我们完全不需要考虑这么多细节,辛勤劳动的程序员哥哥们和工程师姐姐们(互文预警,这里不是说程序员都是哥哥,工程师都是姐姐)早就为我们做好了搭桥铺路的准备工作。技术从来不是高高在上的皇帝,它只是在我们看不到的地方默默服务于我们的生活。
网络通信是一门内容十分丰富的领域。除开那些涉及作者知识盲区的内容,本文所描述的种种技术协议,都仅仅停留在一个抽象的,简化的理论层面。任何一部分内容,展开下去,都可以成为一个单独的方向,比如网卡的设计,路由器的设计,数据链路层协议的代码书写等。这些工作,都不可能仅仅通过一个人的能力来完成的。
事实上,任何现代的工程项目或者系统,只要是稍具规模,都不可以以一人之力来完成。
那些号称以一人之力完成一个项目一个系统的,不是大忽悠,就是民科。