一个网络数据包是如何被发送和接收-送快递原理

1.TCP/IP模型

首先,要了解一条数据被打包的方式,我们要了解的是著名的tcp/ip模型,我相信很多同学们都清楚地学过。

其实tcp/ip模型分为四层:应用层/传输层/网络层/网络接口层。他们每一层都有对应的对数据包的加工方式。 

那么当我们在网址栏中输入网址,到我们接收到服务器的回应,中间到底发生了什么?

2.应用层

应用层只关心为用户提供功能,比如:http,smtp,ftp,dns等等,而不关心具体传输的事情。

2.1 HTTP

首先,你在某个网页的地址栏中输入你想访问的某个网址,首先接待你的,就是工作在应用层的http协议( 或者https协议),它会逐字分析你的URL地址,然后生成对应的http报文。

当然了,除了请求报文,这里也有对应的响应报文:

  

这类报文信息就是确定你的请求方法(get或post),你的http协议以及版本,还有一些首部信息和主体信息,响应报文则会发回状态码。

当然了,这也是为什么应用层的数据单位是报文的原因。

此外,你的小数据已经完成了http报文解析,浏览器就会把它委托操作系统发送给远端的web服务器,不过在那之前,你的小数据需要找到远端服务器的IP地址,而这项公作,由dns服务器来完成。

2.2 DNS域名解析

说到域名解析,我们首先要了解域名,就像我们打电话要知道对方的电话号码,可是我们只会在通讯录上存储联系人的名字而已,一个道理。

dns中的域名由.来分割,越靠右,层级越高,比如:www.server.com,但是实际上,域名后面还有一个被省略的点,其实它的全名应该是:www.server.com.

这随后一个.就是它的根域,其次是它的顶级域.com,最后是它的权威server.com

层层向下的关系使它们呈现一个树状结构:

根域dns服务器:.

顶级域dns服务器:.com

权威dns服务器:server.com

其实域名解析的过程就好比拿着域名一层层地问某个dns服务器,它的域名的IP地址对应的是谁。也就是在通讯录中一个个找你要拨通的名字的电话号码到底是哪个是一样的。。。。

于是客户端就会拿着你的域名向根域发出问侯,问问这个域名的IP地址是啥,然后根域就问顶级域,顶级域呢又问权威dns。那么问题是如何找到根域,其实也很简单,根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中。这样一来,任何 DNS 服务器就都可以找到并访问根域 DNS 服务器了。

因此,客户端只要能够找到任意一台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再一路顺藤摸瓜找到位于下层的某台目标 DNS 服务器。

不过,每次这么问IP地址,是否会过于繁杂了,其实浏览器会自带缓存,缓存一些网站的域名对应的IP,如果浏览器的缓存能直接找到,那么就不用再做域名解析了。

2.3 协议栈

通过 DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈

协议栈在此时只起到一个指南针的作用,它的结构长这样:

协议栈的上半部分有两块,分别是负责收发数据的 TCP 和 UDP 协议,这两个传输协议会接受应用层的委托执行收发数据的操作。

协议栈的下面一半是用 IP 协议控制网络包收发操作,在互联网上传数据时,数据会被切分成一块块的网络包,而将网络包发送给对方的操作就是由 IP 负责的。

此外 IP 中还包括 ICMP 协议和 ARP 协议。

  • ICMP 用于告知网络包传送过程中产生的错误以及各种控制信息。
  • ARP 用于根据 IP 地址查询相应的以太网 MAC 地址。

不过这个时候,你的数据包通常会选择tcp作为传输协议,毕竟手握三次握手和四次挥手的大哥好像就是比udp牛批一些诶 

3.传输层

于是你的数据包顺利来到了传输层 ,传输层有两位著名的大哥,tcp和udp,简单介绍一下:

TCP 的全称叫传输控制协议(Transmission Control Protocol),大部分应用使用的正是 TCP 传输层协议,比如 HTTP 应用层协议。TCP 相比 UDP 多了很多特性,比如流量控制、超时重传、拥塞控制等,这些都是为了保证数据包能可靠地传输给对方。

UDP 相对来说就很简单,简单到只负责发送数据包,不保证数据包是否能抵达对方,但它实时性相对更好,传输效率也高。当然,UDP 也可以实现可靠传输,把 TCP 的特性在应用层上实现就可以,不过要实现一个商用的可靠 UDP 传输协议,也不是一件简单的事情。

当然了,你的数据包选择了tcp协议之后,它会先用自己的报文头格式给你的数据包加上一个tcp报文头,在那之前,它会先计算你数据的长度,如果超过了MSS(TCP 最大报文段长度),就要将数据包分块,这样即使中途有一个分块丢失或损坏了,只需要重新发送这一个分块,而不用重新发送整个数据包。在 TCP 协议中,我们把每个分块称为一个 TCP 段TCP Segment)。

我们先看看tcp报文格式:

端口号的解说没有必要,我相信各位都懂了,我们直接来到第二排,第二排和第三排有一个序号和确认序号,这个我相信看过我另一篇文章中三次握手和四次挥手的小伙伴也懂了。至于接下来的重点就是保留位,其实重点就是其中syn,ack,fin,提到这里,我相信懂三次握手和四次挥手的小伙伴又懂了。

还有一个重要的就是窗口大小。TCP 要做流量控制,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力,别发送的太快,撑死我,也别发的太慢,饿死我。

除了做流量控制以外,TCP还会做拥塞控制,对于真正的通路堵车不堵车,它无能为力,唯一能做的就是控制自己,也即控制发送的速度。不能改变世界,就改变自己嘛。

于是,在经历过tcp的三次握手,之后,你的数据包被分解并套上tcp头部,开始下一段旅程。

而你的数据内部的报文数据也变成了这样:

 

还好,只是加了一些tcp头部,就像包裹被包上了快递袋一样。而你的数据包带着tcp头部来到了网络层。不过根据tcp的分段机制,传输层的单位就是

4.网络层

掌管网络层的大哥,当属是IP协议了。

IP协议的工作其实跟tcp一样,在之前的基础上,为你的数据加上一个ip包头,组成IP报文,实现远程定位。tcp在在执行连接,断开,收发等操作时都需要委托IP将数据封装成网络包发送给通信对象。

我们先来看看IP协议的报文格式:

虽然它这么大一个,不过最重要的部分,是它的格式里有源IP地址和目标IP的地址,这样你就知道,你从dns要来的服务器的IP地址该放哪里了吧?

网络层最常使用的是 IP 协议(Internet Protocol),IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片,得到一个即将发送到网络的 IP 报文。

不过,如果你的电脑有多个网卡,你该选择哪个IP地址发出去呢?

这个时候,诶,上一篇文章提到过的路由表派上用场了 

这里简单说一个例子,在lunix系统中,我们可以通过,route -n来查看当前的IP地址表:

可以看见,一共有两个IP地址和一个默认网关,首先会做一个子网的判断,也就是拿着你的目的IP地址和以上两个子网掩码(genmask)进行与运算,如果得到的结果和前面的destination的任意一个网络号相同,那么说明目的地址和你处于同一个子网,就会选择相同的网络号发出去,如果都不相同,则会选择第三个默认网关,通过交换机发送到路由器,再由路由器发送到其他子网的目的的。具体步骤可参考主页另一片文章。

至此,网络层的传输单位是,而且你的数据包又变成了这个样子:

5.网络接口层

你的数据包在经过各种包装和盖戳之后,终于来到了tcp/ip的底层,网络接口层。不过说实话,人家也是一个盖戳的。它的作用就是在你的IP头部前面再加一个Mac头部并封装成数据帧

MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。

而Mac头部非常明显的信息就是它加入了Mac地址的信息,看过我另一篇博客的同学应该知道,我们最终的传输还是要靠Mac地址,不过,这个发送方的Mac地址可不是最终服务器的Mac地址,而是不停变化的,指引着你的数据下一个站点的mac地址(可能是路由器的,也可能是交换机的)

Mac地址的获取涉及到arp协议,不过多讲解。

发送方的 MAC 地址获取就比较简单了,MAC 地址是在网卡生产时写入到 ROM 里的,只要将这个值读取出来写入到 MAC 头部就可以了。

接收方的 MAC 地址就有点复杂了,只要告诉以太网对方的 MAC 的地址,以太网就会帮我们把包发送过去,那么很显然这里应该填写对方的 MAC 地址。

所以先得搞清楚应该把包发给谁,这个只要查一下路由表就知道了。在路由表中找到相匹配的条目,然后把包发给 Gateway 列中的 IP 地址就可以了。

然后通过arp找到下一站的Mac地址就可以了。

至此,你的数据包又变成了这样:

 它看上去。。。。额,好长好恶心。

至此网络接口层的传输单位就是帧,并且,你的数据已经完成好打包,整装待发了!

6.出口-网卡

之后的步骤就涉及到硬件方面的问题了,网络包只是存放在内存中的一串二进制数字信息,没有办法直接发送给对方。因此,我们需要将数字信息转换为电信号,才能在网线上传输,也就是说,这才是真正的数据发送过程。

负责执行这一操作的是网卡,要控制网卡还需要靠网卡驱动程序

网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。

  • 起始帧分界符是一个用来表示包起始位置的标记
  • 末尾的 FCS(帧校验序列)用来检查包传输过程是否有损坏

最后,网卡会将数据包转换为电信号,通过网线发送出去。

7.送别者-交换机 

首先,电信号到达网线接口,交换机里的模块进行接收,接下来交换机里的模块将电信号转换为数字信号。

然后通过包末尾的 FCS 校验错误,如果没问题则放到缓冲区。这部分操作基本和计算机的网卡相同,但交换机的工作方式和网卡不同。

计算机的网卡本身具有 MAC 地址,并通过核对收到的包的接收方 MAC 地址判断是不是发给自己的,如果不是发给自己的则丢弃;相对地,交换机的端口不核对接收方 MAC 地址,而是直接接收所有的包并存放到缓冲区中。因此,和网卡不同,交换机的端口不具有 MAC 地址

 而交换机通过Mac地址表找到对应的端口,然后把这个数据包发出去,当然,如果你的数据的目的的是在同一个子网,那么你的数据包会直接通过这一步到达目的地,否则,它会根据默认网关,通过交换机到达其他路由器,离开自己土生土长的子网了。

8.出境大门-路由器

网络包经过交换机之后,现在到达了路由器,并在此被转发到下一个路由器或目标设备。

这一步转发的工作原理和交换机类似,也是通过查表判断包转发的目标。

不过在具体的操作过程上,路由器和交换机是有区别的。

  • 因为路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;
  • 交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址。

 

首先,电信号到达网线接口部分,路由器中的模块会将电信号转成数字信号,然后通过包末尾的 FCS 进行错误校验。

如果没问题则检查 MAC 头部中的接收方 MAC 地址,看看是不是发给自己的包,如果是就放到接收缓冲区中,否则就丢弃这个包。

总的来说,路由器的端口都具有 MAC 地址,只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃。

完成包接收操作之后,路由器就会去掉包开头的 MAC 头部。

MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。因此,当包到达路由器之后,MAC 头部的任务就完成了,于是 MAC 头部就会被丢弃

接下来,路由器会根据 MAC 头部后方的 IP 头部中的内容进行包的转发操作。

转发操作分为几个阶段,首先是查询路由表判断转发目标。

具体的工作流程根据上图,举个例子。

假设地址为 10.10.1.101 的计算机要向地址为 192.168.1.100 的服务器发送一个包,这个包先到达图中的路由器。

判断转发目标的第一步,就是根据包的接收方 IP 地址查询路由表中的目标地址栏,以找到相匹配的记录。

路由匹配和前面讲的一样,每个条目的子网掩码和 192.168.1.100 IP 做 & 与运算后,得到的结果与对应条目的目标地址进行匹配,如果匹配就会作为候选转发目标,如果不匹配就继续与下个条目进行路由匹配。

如第二条目的子网掩码 255.255.255.0 与 192.168.1.100 IP 做 & 与运算后,得到结果是 192.168.1.0 ,这与第二条目的目标地址 192.168.1.0 匹配,该第二条目记录就会被作为转发目标。

实在找不到匹配路由时,就会选择默认路由,路由表中子网掩码为 0.0.0.0 的记录表示「默认路由」。

接下来就会进入包的发送操作

首先,我们需要根据路由表的网关列判断对方的地址。

  • 如果网关是一个 IP 地址,则这个IP 地址就是我们要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。
  • 如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到 IP 包头里的目标地址了,说明已抵达终点

知道对方的 IP 地址之后,接下来需要通过 ARP 协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收方 MAC 地址。

路由器也有 ARP 缓存,因此首先会在 ARP 缓存中查询,如果找不到则发送 ARP 查询请求。

接下来是发送方 MAC 地址字段,这里填写输出端口的 MAC 地址。还有一个以太类型字段,填写 0800 (十六进制)表示 IP 协议。

网络包完成后,接下来会将其转换成电信号并通过端口发送出去。这一步的工作过程和计算机也是相同的。

发送出去的网络包会通过交换机到达下一个路由器。由于接收方 MAC 地址就是下一个路由器的地址,所以交换机会根据这一地址将包传输到下一个路由器。

接下来,下一个路由器会将包转发给再下一个路由器,经过层层转发之后,网络包就到达了最终的目的地。

不知你发现了没有,在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输。

至此你的数据包终于到达目的地。

9.客户端和服务器的互相扒皮

 

数据包抵达服务器后,服务器会先扒开数据包的 MAC 头部,查看是否和服务器自己的 MAC 地址符合,符合就将包收起来。

接着继续扒开数据包的 IP 头,发现 IP 地址符合,根据 IP 头中协议项,知道自己上层是 TCP 协议。

于是,扒开 TCP 的头,里面有序列号,需要看一看这个序列包是不是我想要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。TCP头部里面还有端口号, HTTP 的服务器正在监听这个端口号。

于是,服务器自然就知道是 HTTP 进程想要这个包,于是就将包发给 HTTP 进程。

服务器的 HTTP 进程看到,原来这个请求是要访问一个页面,于是就把这个网页封装在 HTTP 响应报文里。

HTTP 响应报文也需要穿上 TCP、IP、MAC 头部,不过这次是源地址是服务器 IP 地址,目的地址是客户端 IP 地址。

穿好头部衣服后,从网卡出去,交由交换机转发到出城的路由器,路由器就把响应数据包发到了下一个路由器,就这样跳啊跳。

最后跳到了客户端的城门把守的路由器,路由器扒开 IP 头部发现是要找城内的人,于是又把包发给了城内的交换机,再由交换机转发到客户端。

 

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值