Linux网络总结之二-TCP协议概述

TCP协议是一款传输层协议,也是网络中最重要的一款协议。这部分我们重点探究网络传输层协议TCP协议的头部。
一 TCP固定头部结构
 Linux网络总结之二-TCP协议概述
TCP固定头部如图所示:
16位源/目的端口号,报文来自哪个端口,要与哪个端口通信。在进行TCP通信时,客服端往往选用系统空闲的端口,而服务器往往选用处于监听状态的端口。
32位序号,在一次TCP通信中,一个传输方向上的每个字节的编号。通常系统给一个随机ISN初始序号值,报文的序号就是ISN+字节的编号。
32位确认号,响应对方发送过来的TCP报文段。通常是收到的32位序号+1。
4位头部长度,标识TCP头部有多少个4字节。
6位保留,TCP保留地址全部置0.
6位标志位,URG表示紧急指针是否有效;ACK确认号是否有效;PSH提示接收端从缓存区读数据;RST要求对方重新建立连接;SYN请求建立连接;FIN关闭连接。
16位窗口大小,TCP流量控制的手段,告知本地TCP缓冲区还能接受多少字节数据。
16位校验和,保证可靠传输,对TCP报文段报文段执行CRC算法来检验是否丢包。
16位紧急指针,用来发送紧急数据。
二TCP连接的建立与关闭
为了探究TCP连接建立的过程,我们进行以下实验:
我是在一台主机上用相同的ip和不同的端口来组成客户端与服务器的socket。所以采用抓取回环网口的包:tcpdump -i lo命令。首先启动服务器:
 Linux网络总结之二-TCP协议概述
再启动一个客户端,观察端口状态:
 Linux网络总结之二-TCP协议概述
这时候状态显示客户端服务器的全双工连接已经建立。
 Linux网络总结之二-TCP协议概述
这时候抓取到的数据包显示,首先客户端主动连接服务器第一次握手:Flags为S,表示syn请求建立连接。随机序号值为seq=2568488890,该步完成后,客户端处于syn_sent服务器处于syn_rcvd。然后服务器紧接着进行确认操作第二次握手ack=2568488891,同时也发送自己的请求连接seq=1673324876,这时客户端的单向连接已经建立处于established状态,服务器仍处于syn_rcvd状态。接下来第三次握手,第3个TCP报文段输出ack=1,这是相对于第二次握手中的seq=1673324876的偏移量,此时服务器的状态也变为established。三次握手完成。
然后接着在客户端随意输入几个字符,服务器会接受到。这时的抓包信息如下:
 Linux网络总结之二-TCP协议概述
此时,端口状态如下:
 Linux网络总结之二-TCP协议概述
该过程客户端与服务器之间的连接依然保持。分析包信息,我们发现Flags域变为了P,即TCP头部的psh标志,它用来提醒应用程序从TCP接收缓冲区中读数据。同时length=7,它表示要读7个字符长度的数据。
最后观察断开连接的过程,首先关闭客户端,此时端口状态如下:
 Linux网络总结之二-TCP协议概述
这是客户端发起的关闭,因为time_wait有2MSL的时间长度,所以客户端还得在time_wait状态多停留一会儿。接着看数据包信息:
 
先看第一次挥手:Flags域为F,表示FIN结束报文段。Seq=8,此时客户端处于FIN_WAIT_1状态,接着服务器发送确认报文段第二次挥手,因为服务器还要再发送一个结束报文段,这两个时间差很小,在数据报中第二次挥手与第三次挥手的信息一并发出,seq=1,ack=2。当第二次挥手完成时,服务器处于close_wait状态,客户端处于FIN_WAIT_2,同时第三次挥手时,服务器处于last_ack状态,客户端处于time_wait。接着客户端发起第四次挥手,整个TCP连接完全断开。我们等待2MSL之后继续观察端口如下:
 

如上,我们可以得到TCP建立与关闭过程中的状态转移图如下:

Linux网络总结之二-TCP协议概述