一、TCP协议的报文格式
在学习TCP协议的三次握手和四次挥手之前,我们先回顾一下TCP协议的报文格式 网络标准OSI七层结构和TCP/IP四层模型。
1、源端口:
源端口表示报文的发送端口,占16位。源端口和源IP地址组合起来,可以标识报文的发送地址。
2、目的端口:
目的端口为报文的接受端口,也占16位。
3、序号
TCP在对数据进行分段的时候,会给每一个TCP报文段添加一个序号,序号字段的值其实是该文段所发送的数据的第一个字节的序号。这样,该文段中的所有字节都有了其对应的序号了。这么做的原因是,TCP是面向连接的可靠服务,这个序号可以保证数据在传输过程中保持有序性,接受端可以通过这个序号确认收到的数据的完整性和先后顺序;
4、确认号
确认号是期望收到对方的下一个报文段的数据的第一个字节的序号
5、数据偏移
数据偏移是指TCP报文段的数据部分的起始处距离TCP报文段的起始处距离。通俗来的来说就是TCP首部的长度。
长度为4位,最大值为15。以4字节为单位。
若固定首部为20字节,则数据偏移值为20/4=5。转化成二进制是0101.
若包含12字节的可选字段(固定20字节+可选字段12字节=32字节),数据偏移值为32/4=8。转换为二进制为1000
数据的最大偏移值为15,对应的首部总长度为15x4=60字节(固定20字节+可选字段40字节)。
6、保留字段
长度为6位,暂时没什么用。
7、控制位
1)紧急字段URG(1位)
当URG=1时,此字段告诉系统此报文中有紧急数据,应该尽快传送。
2)确认字段ACK(1位)
当ACK=1时,表示确认号有效。当建立连接后,所有发送数据的报文中ACK值必须为1。当ACK=0时,表示该数据字段内含有不确定的信息
3)推送字段PSH(1位)
当PSH=1时,报文会尽快发送给目的地,不会对这样的报文段使用换成策略。
4)复位字段RST(1位)
当RST=1时,表示TCP连接出现了严重的差错,必须释放连接;也可以用于拒绝一个无效的或拒绝一个连接请求。
5)同步字段SYN(1位)
当SYN=1时,表示发起一个连接请求。
可以想一想SYN=1,ACK=0;SYN=1,ACK=1分别代表什么情况?
SYN=1,ACK=0 : 表示发送端发起了连接请求,但仅仅是一个请求,没有建立连接。
SYN=1,ACK=1 : 表示接收端同意了来自发生端发起的请求。
6)终止字段FIN(1位)
用来释放连接,当FIN=1时,表示报文的发送端数据已经全部发送完毕,并要求释放连接。
8、窗口字段
占16位。此字段用来控制对方发送的数据量,单位为字节。
一般TCP连接的其中一端会根据自身的缓存空间大小来确定自己的接受端口大小,然后告知另一端,以确定另一端发送窗口的大小。
9、校验和字段
占16位。对TCP头部和数据进行校验和计算,接收端用于对收到的数据包进行验证。
10、紧急指针
占16位。配合URG(紧急字段)来使用,标识紧急数据的最后一个字节的序号,指向紧急数据结束的位置。
二、TCP协议的三次握手和四次挥手
介绍完TCP报文结构后,重难点来了。发送端和接收端通过TCP协议是如何连接的呢?
1、首先来介绍一下TCP的三次握手
假设张三和李四大学在同一个宿舍生活,这时李四刚从图书馆学习完去食堂吃饭,然后待在宿舍的张三给李四打电话,让他带一份饭回来。
第一次握手:张三(客户端)向李四(服务端)发送一个 SYN 报文段,其中 SYN=1表示请求建立 TCP 连接,同时携带客户端的初始序号seq=x。
第二次握手:李四收到请求后,回复一个 SYN+ACK 报文段(SYN=1, ACK=1)。其中 ACK=1 表示确认,ack=x+1(确认序号,表明期望接收的下一个字节序号),同时带上服务端的 初始序号 seq=y,用于告知张三“已收到请求,准备好连接”。
第三次握手:张三发送 ACK 报文段(`ACK=1`),其 seq=x+1(客户端序号递增),ack=y+1(确认服务端序号)。至此,TCP 连接正式建立。此时张三发送真实请求“去食堂带份饭回来”(开始数据传输),李四收到后执行。
2、TCP的四次挥手过程
第一次挥手:张三(客户端)实在饿的不行,有点等不及了,就催李四“买完没啊,快要饿坏了”。然后向李四发送一个 FIN结束请求报文(FIN=1,ACK=1),并携带随机产生的序列号 seq=x,表示客户端不再发送数据,请求关闭连接。
第二次挥手:李四(服务端)听到张三在催他,回复“别着急,给你排队呢”,并向张三发送ACK 确认报文(ACK=1),其中包含服务端产生的序列号 seq=y 和确认号 ack=x+1。此时连接进入半关闭状态,仍可传输数据(如李四说“再有几分钟就好了”),但客户端不再发送新数据(张三已经饿的说不出话来了)。
第三次挥手:李四买完饭后,跟张三说“饭买好了,马上回去”。然后向张三发送 FIN结束请求报文(FIN=1,ACK=1),携带服务端随机产生的新序列号 seq=a,以及确认号 ack=x+1,表示服务端数据已全部传送完成,请求关闭连接。
第四次挥手:张三收到李四的 FIN报文后,向李四发送 ACK确认报文(`ACK=1`),seq=x+1,ack=a+1。之后进入等待状态,经过 2MSL(最长报文段寿命)时间,确认无其他数据传输后,才主动挂断电话,彻底关闭连接。
这就是TCP的四次挥手过程