分享

一文秒懂 TCP/IP实际五层结构(下篇)

 启云_9137 2020-10-20

(详解TCP/IP协议之:传输层TCP协议)

阅读本文大约需要15分钟,您可以先关注我们或者收藏文章,避免下次无法找到。

一文秒懂 TCP/IP实际五层结构(下篇)

引言

本运维老狗在TCP/IP实际五层结构的上篇和中篇中详细讲解了TCP/IP实际结构,以及以太网协议、IP协议、和UDP协议。有同学留言催更,迫切的想看本老狗对TCP协议的讲解。

应同学们的要求,TCP/IP实际五层结构(下篇)又在运维间隙中赶制出来了。废话不多少,直接上干货。

TCP协议介绍

我们在中篇中介绍了传输层的UDP协议,这里我们来看看传输层的另外一个协议,TCP协议。虽然它俩同属传输层,但它俩的性格完全不同。如果把UDP协议形容为愣头青,则把TCP协议形容为诸葛亮一点不为过。TCP协议'做事'三思而后行、运筹帷幄。

TCP协议有丰富的特性,支撑着它的'诸葛亮'形象,比如它有连接管理机制、滑动窗口、窗口控制、重发机制、流控制、拥塞控制、慢启动、快速重传等等功能,不可谓不丰富。

这些名词看起来深奥难懂,但同学们不用担心,虽然TCP协议是TCP/IP协议簇中最复杂的协议,但本老狗会努力尝试用简单的语言讲透TCP协议。

TCP提供一种面向连接的、可靠的字节流服务。面向连接意味着两个使用TCP的应用在彼此交换数据之前必须先建立一个TCP连接,也就是说要先建立通道,后面数据才能在通道中传输。

小做复习,回顾一下TCP首部的位置。TCP数据报作为IP数据报的数据部分,包含在IP首部中。如下图所示:

一文秒懂 TCP/IP实际五层结构(下篇)

TCP首部

TCP首部比较复杂,TCP首部正常为20个字节(不包含选项部分),如果选项部分有内容,最大可达60个字节。下面来分析IP首部的具体组成。

一文秒懂 TCP/IP实际五层结构(下篇)

(1)源端口号(16位)、目的端口号(16位)

端口号用于标识应用层的协议。

其中1-1023为知名端口号和预留端口号。

1024-65535为临时端口号,分配给应用临时使用

(2)序列号(32位):序列号,有的资料中也叫做'序号'

(3)确认序列号(32位):Ack,有的资料中也叫做'确认应答号'

老狗这把序列号和确认序列号串起来讲,先使用醉汉和他老婆做个比喻。

序列号就像一个醉汉,确认序列号就像他的老婆。醉汉说话老是重复,他老婆听后一直在提醒他:'嗯,这句话你说过了',醉汉说着说着打起了呼噜,他老婆推醒他:'死鬼,醒醒,你刚才说的咱家有大额存款,在哪儿呢,快说说'。

这里可以看出,发送端有时候会发送重复序列号的数据包,确认序列号可以帮其找出重复数据包。同时,发送端有时候还会出现超时为应答等情况,确认序列号通过重传机制告知发送端。

序列号和确认序列号的作用大致说清楚了,下面看个图,再做些说明。

一文秒懂 TCP/IP实际五层结构(下篇)

序列号由随机生成的32bit数值作为初始值。序列号的数值是指发送数据的相对位置。每发送一次数据,就累计加一次该数据字节大小。另外,在建立连接和断开连接时发送的SYN包和FIN包虽然并不携带数据,但是也会作为一个字节增加对应的序列号。

确认序列号的数值为发送确认的一端所期望收到的下一个序号。因此,确认序列号应当是上次已成功收到数据字节序号加 1。

刚才说到'序列号由随机生成的32bit数值作为初始值',有同学会顿生疑问,他看到的TCP会话的seq都是从0开始的,这又是怎么回事?

这里做个解释,wireshark为了让咱们分析数据包时的方便,使用了相对序列号。可以在wireshark的首选项中找到这个选项,不喜欢使用相对序列号的同学可以去掉勾选,如下图:

一文秒懂 TCP/IP实际五层结构(下篇)

(4)首部长度(4位):

该字段长4位,单位为4字节,即TCP首部的最大长度可为15*4=60个字节。正常的首部长度为20个字节,因此选项部分的最大长度可为40个字节。

通过下图展示的数据包,可以看到首部字段值的二进制是'0101',换成十进制就是5。计算出来首部长度是:4字节*5 = 20字节。

一文秒懂 TCP/IP实际五层结构(下篇)

看图仔细的同学会发现上图中有[TCP segment Len:1396]的字眼。但同时会发现,TCP首部中并没有关于TCP段(即数据部分)长度的字段。

下图为点击到这个字眼上的情况,发现下面的十六进制的着色位置和上图一样。

一文秒懂 TCP/IP实际五层结构(下篇)

老狗这里做个解答。这个字眼的内容是用'[]'框起来的,意思就是不是通过直接读数据读出来的,而是wireshark计算出来的。

计算过程如下:Frame长度1450字节,Ethernet首部14字节,IP首部20字节,TCP首部20字节。这么一算,正好TCP数据部分是1396字节。

(5)保留(6位):暂无作用

(6)控制位(6位):在TCP首部中有6个控制位。它们中的多个可同时被设置为1。

一文秒懂 TCP/IP实际五层结构(下篇)

URG:紧急指针。

ACK:确认序号有效(确认应答):TCP规定除最初建立连接是的SYN包外,其他数据包ACK必须置位。

PSH:接收端应该尽快将这个报文段交给应用层。PSH为0时,则不需立即传送而先进行缓存。

RST:重置连接,RST为1时表示TCP连接出现异常,必须强制断开连接。

SYN:同步序号用来发起一个连接

FIN:发端完成发送任务:置位后表示此端不再有数据发送,希望断开连接(单向传输断开)。

(7)窗口(16位):

TCP的流量控制是由连接的每一端通过声明各自端的窗口大小来控制的。窗口字段占用16 bit,即窗口的范围为0-65535字节。这里先提一嘴,通过选项部分的窗口扩大因子(windows scale)可将窗口扩大为32bit字段。

说完窗口大小,接下来看看滑动窗口。

滑动窗口的引入,是为了解决'停止等待'的缺点的。'停止等待'顾名思义,就是一端发送一次数据后,就必须停止发送数据,等待对端回复确认后,再进行发送。这种方式导致网络传输效率低下。反观滑动窗口机制,在窗口内的数据即使没有收到确认应答也可以继续发送数据。窗口的小大就是指无需等待确认应答而可以继续发送数据的最大值。

滑动窗口的机制如下图所示。

一文秒懂 TCP/IP实际五层结构(下篇)

从图中看到,滑动窗口的大小为6字节(仅做展示),此时已经滑动至第4-9字节的位置,说明第1-3字节已经发送完成并被确认。第4-6字节刚被发送,还未确认,此时可用的窗口大小还剩3字节(第7-9字节)可以继续发送并不用被立刻确认。同时,第10字节之后的数据还未包含在窗口内部,暂时不能发送。

老狗这里说个知识点,滑动窗口的大小不是随时更新,也不是发送ack确认后就会增大。需要等到接收端的缓存数据已经被应用层读走,并且接收端主动更新自己的窗口后。发送端才能发送更新后窗口大小的数据。

(8)检验和(16位):

检验和覆盖了整个的TCP报文段: TCP首部和TCP数据。检验和一个强制性的字段。

(9)紧急指针(16位):

紧急指针只有在URG为1时才有效,用于处理紧急数据。一般在暂时中断通信的情况下使用。比如在web浏览器上点击停止按钮,或者在telnet时输入crtl+c时,都会有URG置位的数据包。

(10)选项(0-60字节):

常用的选项包括MSS、窗口扩大因子、SACK等,下图展示TCP握手的SYN阶段数据包的选项内容:

一文秒懂 TCP/IP实际五层结构(下篇)

这里重点介绍一下MSS、窗口扩大因子、选择性确认(SACK)

MSS 最大分段长度:TCP数据包每次传输的最大数据分段大小,数据分段大小指的是IP数据包的数据(TU值减去IPv4 头部和TCP的头部得到的值)。

TCP协议在建立连接的时候通常要协商双方的MSS值,通讯双方会根据双方提供的MSS值的最小值确定为这次连接的最大MSS。

MSS的协商过程如下图所示:

一文秒懂 TCP/IP实际五层结构(下篇)

窗口扩大因子: WS是一个用来改善TCP吞吐量的选项。可将原有窗口大小扩充至32bit。

窗口扩大因子只有主动连接方的第一SYN可以发送携带。

窗口扩大因子只有在发起方的第一个SYN中包含,接收端收到带有窗口扩大因子的选项后,可以发送自己的窗口扩大因子(如果支持)。只有在双方都支持的情况下,后续数据才能使用扩大后的窗口。

咱们现在抓包看看窗口扩大因子,如下图。第1帧中看到ws=256,即原有窗口大小扩容256倍。通过展开分析,看到窗口扩大因子使用了8位(即窗口大小扩容2的8次方倍)。第2帧的分析与第1帧相同,窗口扩容128倍。

一文秒懂 TCP/IP实际五层结构(下篇)

SACK(确认选择):SACK使TCP拥有了选择确认的能力。

当发送端收到接收端返回的SACK后,就知道哪些报文时接收端已经收到的,进而将接收端没有收到的报文进行重传。注意:SACK协议需要通信双方都支持。

SACK允许选项(类型值为4),该选项只允许在有SYN标志的TCP包中(会话建立时的前两个包),分别表示是否支持SACK功能。

一文秒懂 TCP/IP实际五层结构(下篇)

SACK选项(类型值为5),选项长度可变,用来选择性的确认数据的序列号范围。

TCP会话的建立与终止

TCP会话的建立过程如下图所示。为了方便查看,我们这里用相对序列号来进行展示。

一文秒懂 TCP/IP实际五层结构(下篇)

(1)第一次握手

客户端执行主动打开(active open)连接,发送一个SYN段指明客户端打算连接的服务端的端口,以及初始序号(ISN)。

发送内容包括:SYN=1,Seq=J

(2)第二次握手

服务器端收到SYN,执行被动打开(passive open)连接,服务器发回包含服务器的初始序号的SYN报文段,作为应答。同时,将确认序号(Ack)设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。

发送内容包括:SYN=1,ACK=1,Seq=K,Ack=J+1

(3)第三次握手

客户端收到服务器ACK回包后,首先进入ESTABLISHED状态,之后发送ACK给服务器,最后服务器也进入ESTABLISHED状态。

发送内容包括:ACK=1,Seq=J+1,Ack=K+1

TCP会话的结束过程如下图所示,为了方便查看,我们这里仍用相对序列号来进行展示。

一文秒懂 TCP/IP实际五层结构(下篇)

(1)第一次挥手

客户端主动关闭,进入FIN_WAIT_1状态,收到FIN包的服务器端进入被动关闭CLOSE_WAIT状态。

发送内容包括:FIN=1,ACK=1,Seq=M,Ack=Z

2.第二次挥手

服务器端收到FIN包之后,会向客户端回送ACK,客户端收到后,进入FIN_WAIT_2状态 (FIN也占用一个序列号)。

发送内容包括:ACK=1,Seq=Z,Ack=M+1

3.第三次挥手

服务器端进入LAST_ACK状态,发送FIN包至客户端,客户端收到后进入TIME_WAIT状态(即2MSL状态)。发送内容:FIN=1,ACK=1,Seq=N,Ack=M+1

4.第四次挥手

客户端收到FIN包之后,会向服务器端回送ACK,服务器端收到后,进入CLOSEE状态。发送内容: ACK=1,Seq=M+1, Ack=N+1

注意:ACK不占序列号,SYN和FIN各占用1字节序列号。

TCP状态迁移

TCP状态迁移是个复杂的过程,下图(图片来自网络)展示了TCP状态迁移的全貌,图中用粗的实线箭头表示正常的客户端状态变迁,用粗的虚线箭头表示正常的服务器状态变迁。

一文秒懂 TCP/IP实际五层结构(下篇)

TCP状态迁移中的一些状态。

(1)FIN_WAIT_2状态

在FIN_WAIT_2状态客户端已经发出了FIN,并且服务端也已对它进行确认。除非客户端在实行半关闭,否则将等待另一端的应用层意识到它已收到一个文件结束符说明,并向客户端发一个FIN来关闭另一方向的连接。只有当另一端的进程完成这个关闭,客户端才会从FIN_WAIT_2状态进入TIME_WAIT状态。

这意味着客户端可能永远保持这个状态。另一端也将处于CLOSE_WAIT状态,并一直保持这个状态直到应用层决定进行关闭。所以需要定时器来结束这个状态。

一般防火墙都有解决FIN_WAIT_2状态的超时时间设置。如果超时,防火墙会向双向发送RESET来踢掉连接。

(2)2MSL等待时间

TIMEWAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL。它是任何报文段被丢弃前在网络内的最长时间。不同的操作系统有不同的规定,常用值是30秒,1分钟或2分钟。在2MSL等待期间socket使用的本地端口默认情况下不能再被使用。这个端口只能在2 MSL结束后才能再被使用。

以上之所以说默认情况下才有2MSL,是因为Linux系统有个端口快速回收机制。通过将cat /proc/sys/net/ipv4/tcp_tw_recycle设置为1,将cat /proc/sys/net/ipv4/tcp_timestamps设置为1,来实现TIME_WAIT状态快速回收,即无需等待两倍的MSL这么久的时间,而是等待一个重传时间即释放端口。

(3)TCP重传

TCP的重传分为两种:超时重传、确认重传(又叫快速重传)

首先来看第一种重传,超时重传。以客户端发送数据包至服务器端,但服务器端超时仍不进行回复确认(这里指的不回复,可以是客户端发送数据时丢包,或者服务器端回复时丢包),则启动超时重传机制。重传的数据分析过程下图所示。同时超时重传遵循的退避机制。

一文秒懂 TCP/IP实际五层结构(下篇)

接下来看第二种重传,确认重传(也叫快速重传),用于未启用SACK的情况下。举例说明,如下图所示。:如果客户端发出了1,2,3,4,5份数据,第一份先到送了,于是服务器端就发送Ack=2,结果2号包因为某些原因没收到,3号包到达了,还是Ack=2,后面的4号和5号包都到了,但是还是Ack=2,因为2还是没有收到,于是发送端收到了三个Ack=2的确认(这里就是确认重传),知道了2号包还没有到,于是就马上重传2号包。于是,服务器端收到了2号包,此时因为3,4,5号包都收到了,于是Ack=6,则客户端发送的6份数据都进行了确认。

一文秒懂 TCP/IP实际五层结构(下篇)

总结

本篇着重介绍了TCP协议,包括TCP协议TCP首部构成、TCP会话的建立和终止过程、及TCP状态迁移中常用的一些状态。

通过本篇的介绍,并结合上一篇UDP的介绍,同学们应该能够看到UDP和TCP的区别了。就因为它们直接有明显的区别,才造成了它们两者的应用场景完全不同。

UDP协议无状态,传输效率高,可用于视频类、音频类、广播类的服务中。

TCP协议有状态,而且传输可靠,可用于文件传输、网页浏览、邮件收发等服务中。

至此TCPIP协议实际结构的五层结构的基本框架就勾勒出来了,有兴趣的同学到IT管理局中可以把三篇文章结合起来学习,效果更佳哦。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多