网络协议学习之一:网络请求是如何发出

来源:互联网 发布:hosts网络源 每日更新 编辑:程序博客网 时间:2024/05/22 03:40

最近突然对网络协议有了兴趣,很想知道一个简单对网络请求是如何发送出去的。我们都知道,所谓发送数据,无非是把一串0/1比特发给接收方,拿最常见的场景来说,我们通常连接的wifi网络,计算机把一串0/1发给它,它是如何接收,如何识别该到那个地方截止是发送方的一个完整包呢?
这就要靠协议来支持了,所谓协议,就是大家共同约定好,共同遵守的一些规则而已。就好比国家与国家之间通常也会由很多协定,协议,备忘录之类的文件,其实也就约定了双方在处理问题时的一些默契。而回到计算机协议,由于在计算机的世界都是0和1,所以计算机的协议通常就是约定双方对这一串的0/1怎么处理,比如,哪几个0/1表示元数据,哪几个表示分界符,哪几个是真正的数据,等等。

宏观过程

这里写图片描述

图1. 协议栈图

上图表示了数据从用户产生到可以被发送出去到封装过程,也就是我们常看到到协议栈的流转过程。分层协议栈的好处自不必多说,就是分层管理,模块化的典型思想,每一层只处理特定的问题,并为上层提供服务。从图中可以看到,每一层往下,都会添加一个首部作为元数据,并作为整个数据部分递交给下层。各层添加的元数据各不相同,但基本目标都是方便管理本层的数据包。

具体过程

我们知道现在计算机出厂一般都自带网卡,网卡实现了MAC层协议,复制数据报文的收发。我们也知道,tcp/ip协议栈族是由操作系统实现的,并封装了接口作为系统调用供外部使用。
有了这两点认识,我们就可以顺畅的分析整个数据包的流转。应用层调用操作系统提供的接口将数据传入,经由系统内部处理后到达网卡(准确地说应该是到达网卡的缓存),再由网卡驱动将数据封装成MAC帧后通过底层信道发送出去。
数据从应用层经系统内部处理的过程如下图所示:
这里写图片描述

图2. 数据发送在操作系统内部的流转

问题1:有人就问了,那连续的数据到达后,最后封装成MAC帧后其实都是一串连续的比特,接收方是如何识别哪是开头,哪是结尾呢?

先解释下协议栈图中的MAC层和物理层几个标示。FCS是帧检验序列,用于接收方校验所收到的帧是否有差错,一般用的是CRC校验方式。而物理层翻译成比特流后,前面插入的8个字节是用作同步与帧起始定界符(其中前7个字节是同步码,最后一个字节是表示帧定界符),所谓同步码,是告诉接收方赶紧准备好接收数据,以免数据到达时接收方尚未准备好,白白浪费资源。

问题2:有人又问了,前面的起始定界符好理解,标示比特流中这里是帧的开头呗,那结尾咋办,一连串的比特过来,总得有个尾定界符告知接收方这里是帧的结尾吧。

其实这是个好问题,一般来说,在数据链路层封装成帧的方案中,很明显是要首尾定界符方能确定一个完整的帧。但是现在广泛使用的以太网MAC帧中却是没有定义结尾定界符的,这是因为它不需要,它有其他方式可以让接收方识别出结尾。窍门就在发送物理层比特流的时候,以太网采用的是曼彻斯特编码(不是联队,^_^),这种编码的一个特点是每个0或1码元都有一次高低电平转换(而不经编码的话,传统的就是1是高电平,0是低电平,这导致碰到连续的0或1的时候,接收方收到的就是连续的高电平,或者连续的低电平,无法提取这里面到底有多少个1或0),有了这种编码,那么接收方就可以确定在没有电平转换的时候,就是帧的结尾,哈哈,这么看这也是一种约定。

问题3:那还有人问了,要等到没有电平变化的时候才能确定结尾,那不是没发一个帧都要等待一会,那如果我要连续的发送咋办?

这也是个好问题,其实解决方案很简单,就是强制约定没发一个帧之间都要等待一个间隔,让接收方识别帧结尾,不允许连续的发送帧。当然这么强制也是有道理的,一个是避免了插入帧定界符,再一个是我们还要注意到以太网一般使用广播信道,其中使用的是CSMA/CD协议,也就是常说的载波监听/碰撞检测协议,这个协议说的其实是发送前先监听,边发送边监听,一旦检测到碰撞就立即停止发送。从这点看,如果一直连续的发送帧,那么就相当于连续的占用着共享信道,导致其他发送方因碰撞而无法发送,甚至被一直阻塞。所以,每发送一个帧,就留出点空隙,让其他发送方可以检测信道是否空闲,公平竞争信道资源,这样一举两得,何乐而不为呢。

问题4:就算前面的都没问题了,那网卡在发送比特流的时候,总不会一个一个比特的发送吧,那也太慢了。

其实这就是个串并行的问题,我们看现在的网线,都是8个引脚绞在一块,这可不是为了好看,事实上,计算机处理相关的东西都是以字节作为基本单位,因此8个引脚绞在一块,每次可以发送一个字节,既可以并行发送提高了速率,也方便了处理。至于无线网卡,虽没有拆开看过,但是原理应该是不变的,只是由发送电信号,转而发送电磁信号,所以应该也是8个比特一块发送,或者是更多倍数,如果路由器支持的话。

总结:看来这简单的发送请求的过程,其实背后还是隐藏着很多的东西,只是因为封装的好,我们不太感知。细细想起来每个过程都还是由很多值得关注的,所谓知其然也知其所以然。

备注:
1. 图二来源于文章https://www.kancloud.cn/digest/protocol/153401 ,在此谢过作者,也是看了其文章才把整个流程贯通起来。
2. 文章中很多知识点的解答都来源于谢希仁老师编著的<<计算机网络>>,虽说当时看的不怎么懂,但回过头来细翻,还是颇有收获。