3 记一次 Tcp Ip完整的数据包传输过程
读此文章之前,先弄懂下面5个基本知识点:
- 封装报文是从上层到下层(应用层 –> 传输层 –> 网络层 – > 数据链路层 –> 物理层),解封装报文是从下层到上层。 实际例子:从PC1远程登录服务器(Server)。
- 数据包传输的过程中,源IP和目标IP不会变,除非遇到NAT(SNAT或DNAT),源MAC和目标MAC遇到网关会变。
- 二层内通过MAC寻址,三层通过IP寻址。
- 当一个数据包的目的地址不是本机,所以需要查询路由表,当查到路由表中的网关之后,需要获取网关的MAC地址,并将数据包的MAC地址修改成网关地址,然后发送到对应的网卡。
- 协议数据单元在应用层、表示层和会话层被称做数据(Data),在传输层被称做分段(Segment),在网络层被称做包(Packet),在数据链路层被称做帧(Frame),在物理层被称做比特(Bit)。
- PC1或者Server上保留的arp表是:arp和ip的映射关系。而二层交换机是arp和端口的映射关系,也就是这个arp 应该由哪个端口转发。三层交换机可以保留arp和ip的映射关系。
这张图片会贯穿本文始终
这个你要首先弄明白,当数据包从PC1发出时,它已经是一个完整的包了,包含如下信息:
PC1发出的包所包含的信息
应用层:HTTP协议是生成针对目标WEB服务器的HTTP请求报文,该报文就是需要传递的数据
传输层:HTTP协议使用的是TCP协议,为了方便通信,将HTTP请求报文按序号分为多个报文段(segment),并对每个报文段进行封装。PC1使用本地一个大于1024以上的随机TCP源端口(这里假设是1030)建立到目的服务器TCP80号端口的连接,TCP源端口和目的端口加入到报文段中,学名叫协议数据单元(Protocol Data Unit, PDU)。因TCP是一个可靠的传输控制协议,传输层还会加入序列号、窗口大小等参数
网络层:下沉到网络层后,封装网络层的头部,主要就是添加源和目的IP地址,成为数据包。用户通常使用主机名或域名来访问服务器,这时就需要通过应用层的DNS服务来通过域名查找IP地址,或逆向从IP地址反查域名。这里的源IP地址是193.1.1.2,目的IP地址是195.1.1.2。
数据链路层:下沉到数据链路层,封帧的头部,源MAC和目标MAC。PC1比较去往的目标IP,发现Server IP 195.1.1.2不在本地网络中,PC1通过查找本地路由表,会有一条默认路由指向网关R1,知道数据包要先发到网关R1的Fa0/0口。PC1查找本地arp cache,如果找到193.1.1.1对应的MAC地址则进行封装; 如果在ARP cache中没有找到193.1.1.1对应的MAC地址,则用ARP协议,査询到网关对应的MAC地址 “00-11-BC-7D-25-03” 。于是,这里的源MAC地址是PC1的MAC地址“00-1B-24-7D-25-01”,目的MAC地址是网关的MAC地址“00-11-BC-7D-25-03。
从PC1发出的数据帧格式:

物理层:数据链路层封装后的数据帧下沉到物理层,转换成二进制形式的比特(Bit)流,从PC1的网卡发送出去。
对你没看错,这里PC1外接的是一个集线器,按理说这么古老的设备是不应该出现在这里的,但是为了能够全方位的描述一些你常见到的设备,这里有意为之,安排了一个集线器。
PC1发出的比特流到达集线器,集线器简单地对比特流转发,从除接收端口以外的所有端口转发出去。PC2接收到这个数据包,把比特流转换成帧上传到数据链路层,PC2比较数据帧的目的MAC地址,发现与本机网卡的MAC地址不同,PC2丢弃该数据帧,放弃处理,数据到达路由器。
路由器R1收到该比特流,转换成帧上传到数据链路层,路由器R1比较数据帧的目的MAC地址,发现与路由器接收端口Fa0/0(快速以太网,简写成Fa0/0,指的是0号插槽上编号为0的接口)的MAC地址相同,路由器知道该数据帧是发往本路由器的。路由器R1的数据链路层把数据帧进行解封装,然后上传到路由器R1的网络层,路由器R1看到数据包的目的IP地址是195.1.1.2,并不是发给本路由器的,需要路由器进行转发。
路由器R1査询自己的路由表,发现数据包应该从串行接口S1/1发出。路由器R1把数据包从Fa0/0接口交换(forward)到S1/1接口。
此时R1并不能直接把这个数据包发出去,因为在R1的Fa0/0接口被解封装,现在需要被重新再封装,即在路由器的入接口解封装,在路由器的出接口需要再封装。网络层的封装并没有被解开,但并不意味着网络层的信息一点都没有改变,其实网络层的数据包中源和目的IP地址都没有被改变(除非在网络地址转换的情况下),但TTL(生存周期)会减1。
网络层把数据包交给下层的数据链路层,数据链路层需要封装二层的地址。路由器间一般使用串行链路互联。串行链路不同于以太网,因为以太网是一个多路访问的网络,要定位到目的设备需要借助于MAC地址,但串行线路一般的封装协议都是PPP(Point-to-Point Protocol,点到点协议)或HDLC(High-Level Data Link Control,高级数据链路控制协议)封装,这种封装被用于点对点线路,也就是说,一根线缆只连接两台设备,一端发出,另一端肯定可以收到(有点像容器网络中用的veth)。假设串行线缆上使用的是PPP协议,则数据链路层封装的源和目的地址都是PPP。
数据链路层封装后的数据帧被传到物理层,转换成二进制形式的比特流,从路由器R1的S1/1接口发送出去
从R1的S1/1发送出去的包的数据帧格式:

路由器R2收到这个比特流,上传至数据链路层,数据链路层去掉PPP的封装。路由器R2査询数据包的目的IP地址,发现该IP网络直接连接在Fa0/0接口,路由器R2把数据包交换到Fa0/0接口。路由器查看本地的ARP缓存,如果找到195.1.1.2对应的MAC地址,则直接进行封裝;如果没有找到,则发送ARP的查询包。路由器R2发出数据帧的源地址是Fa0/0接口的MAC地址,目的地址是服务器网卡的MAC地址。
数据链路层封装后的数据帧被传到物理层,转换成二进制形式的比特流,从路由器R2的Fa0/0接口发送出去。
源MAC已经变为R2的F0/0的MAC,目标MAC则根据ARP求得
路由器R2发出的比特流到达交换机,根据源MAC地址进行学习,根据目的MAC地址进行转发。交换机根据数据帧中的目的MAC地址査询MAC地址表,把比特流从对应的端口发送出去,交换机把比特流发往服务器,并没有发往PC3。可以看到交换机并没有像集线器那样进行广播转发,而是有针对性的进行了转发。
服务器接收到这个比特流,把比特流转换成帧格式,上传到数据链路层,服务器发现数据帧中的目的MAC地址与本网卡的MAC地址相同,服务器拆除数据链路层的封装后,把数据包上传到网络层。服务器的网络层比较数据包中的目的IP地址,发现与本机的IP地址相同,服务器拆除网络层的封装后,把数据分段上传到传输层。传输层对数据分段进行确认、排序、重组,确保数据传输的可靠性。数据最后被传到服务器的应用层。
服务器收到PC1发过来的数据后,对PC1进行响应。和PC1处理的过程类似,服务器也知道要发往一个远程的网络,数据链路层的目的MAC地址需要封装网关的MAC地址;网络层源和目的IP地址与PC1发送过来的包相反,即把源地址变成目的地址,目的地址变成源地址;传输层源和目的端口与PC1发送过来的包相反,即把源端口变成目的端口,目的端口变成源端口。

从PC1到Server的整个数据包流动过程,PC1执行OSI七层的封装,然后把比特流传到集线器;集线器在物理层把信号简单放大后(这是它的主要功能,为了增加有效的传输距离),把比特流传到路由器R1;R1执行OSI下三层的处理后,再把比特流传到路由器R2;R2执行OSI下三层的处理后,再把比特流传到交换机;交换机执行OSI下二层的处理后,再把比特流传到服务器
从这个流动过程中,可以发现数据流在中间设备上主要执行的是OSI下三层的操作。
- 物理层的设备不改变帧的格式,广播式转发。
- 数据链路层的设备也不改变帧的格式(比如二层交换机),但可以根据数据帧中的目的MAC地址进行转发;
- 网络层的设备改变帧的格式,要执行帧的解封装和再封装,但不改变数据包中的源和目的IP地址(NAT除外),即每一跳只会变更目标MAC地址。



- 路由器收到数据包后,报文送到数据链路层,数据链路层解封以太网帧头部,提取目的MAC地址
- 查看目的MAC地址是不是自己本身的MAC地址。这个时候出现两种情况,具体如下:
- 情况1:是本机的MAC地址,则把报文传到网络层,由网络层继续解析。
- 情况2:不是本机的MAC地址,则丢弃报文。
- 假设是情况1,目的MAC是自己的MAC,把报文送到网络层解析。
- **送到网络层后,网络层解析,提取目的IP地址,判断目的IP地址是不是本机的IP地址。**这个时候再次出现两种情况,具体如下:
- 情况1:是本机IP,则把报文送到上层,由传输层进行解析。由于本次主要讲解转发流程,就不讲传输层解析的过程了。
- 情况2:不是本机IP,则去查路由表,匹配出接口。
- 假设是情况2,不是本机IP,查路由表根据路由的最长掩码匹配原则,匹配路由表,找到出接口。查路由的时候会出现四种情况,具体如下:
- 情况1:没有匹配路由,无法继续转发,则丢弃报文。并向源IP发送目的不可达的ICMP报文。
- 情况2:匹配直连路由,网络层封装目的IP和源IP,使用目的IP地址查ARP表。寻找目的MAC。
- 情况3:匹配非直连路由,网络层封装目的IP和源IP,使用路由表里的下一跳IP地址查ARP表(不会修改目的IP)。寻找下一跳IP地址的目的MAC。
- 情况4:匹配默认路由,网络层封装目的IP和源IP(不会修改IP),使用路由表里的下一跳IP地址查ARP表。寻找下一跳IP地址的目的MAC。
- 假设匹配到路由,去ARP表,匹配目的IP对应的MAC地址。这个时候出现两种情况,具体如下:
- 情况1:在ARP表里匹配到了对应的MAC地址,则把匹配到的MAC封装到帧头部的目的MAC,把本机出接口的MAC封装到帧头部的源MAC里。然后发送出去。
- 情况2:在ARP表里没有匹配到对应的MAC地址,则发送ARP请求,寻找目的IP对应的MAC地址。
- 假设没有匹配到对应的MAC地址,发送ARP请求,这个时候会遇到两种情况。具体如下:
- 情况1:没有收到ARP响应,无法继续获取目的IP对应的MAC地址。则丢弃报文。
- 情况2:收到了ARP响应,首先把响应报文中的源MAC解析出来,然后把目的IP和从响应报文中获取的源MAC放到ARP表中,形成映射关系,并对这个映射关系添加老化时间。然后把MAC封装到目的MAC里,把本机出接口的MAC封装到源MAC里,然后发送出去。
说明:
1、上述中,网络层为了读取目标IP,需要先对网络层的header进行解包、解析,获取IP后再进行封包。这点不知道是否正确,是否可以理解为包到达网络层后,直接就可以读取网络层的header,无需将header去掉。只有当报文要继续向上层(传输控制层)发送的时候,才会去掉网络层的header。(概括地说,无论是在哪一层,如果判断目标(MAC/IP)是自己时,才会将自己层的header去掉,然后发送的自己的上一层)
好像是需要先解包再封包,因为要修改head中的数据,比如ip header中的TTL每经过一个router就减一。
2、网络层会查看报文的dst IP,如果不是本机,就会查看路由表来判断将哪个IP的MAC地址作为链路层header中的目标MAC。
3、报文在到达最终的目标IP服务器前,只是在路由器之间传递时,可以理解为只会对链路层的header进行替换,不会对网络层的header替换。即每跳都需要更换MAC地址。只有路由器需要做NAT(出口路由器、入口路由器)时,才会修改IP地址。
交换机:MAC表,端口号与MAC对应关系;
路由器:arp表,IP与MAC表对应关系;