Appearance
TCP是什么
TCP(Transfer Control Protocol),传输控制协议,是传输层协议,负责端(应用端口)到端的通信,是面向链接的、可靠的协议。
TCP全双工的,要求发送方和接收方的发送功能和接收功能都是正常的,所以TCP链接需要三次握手
TCP报文首部格式

1.源端口和目的端口(Source Port和Destination Port):分别占用2个字节,用于区别主机中的不同进程,而IP地址是用来区分不同的主机的,源端口号和目的端口号配合上IP首部中的源IP地址和目的IP地址就能唯一的确定一个TCP连接。
2.序号seq(Sequence Number):占4个字节,用来标识从TCP发端向TCP收端发送的数据字节流(tcp传输的每一个字节都按顺序编号),它表示在这个报文段中的的第一个数据字节在数据流中的序号。主要用来解决网络报乱序的问题。
3.确认号ack(Acknowledgment Number):占4个字节,确认序列号包含发送确认的一端所期望收到的下一个序号,因此,确认序号应当是上次已成功收到数据字节序号加1。不过,只有当标志位中的ACK标志为1时该确认序列号的字段才有效。主要用来解决不丢包的问题(确认序号减去上次收到的序号等于本段收到的报文的长度)。
4.数据偏移(Offset):占4个bit,指出tcp报文段的数据起始处距离tcp报文段的起始有多远,这个字段实际指出Ttcp报文段的首部长度。需要这个值是因为任选字段的长度是可变的,它用来表示首部中32bit(4字节)字的数目,因此最多能表示15个32bit的的字,即4*15=60个字节的首部长度),因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节。
保留:占6bit。TCP Flags:TCP首部中有6个标志比特,它们中的多个可同时被设置为1,主要是用于操控TCP的状态机的,依次为URG,ACK,PSH,RST,SYN,FIN。每个标志位的意思如下:
紧急URG:当URG = 1时,表示TCP包的紧急指针域有效,告诉系统这个报文段中有紧急数据,应当尽快传输。
确认ACK:TCP应答号将会包含在TCP数据包中,有两个取值:0和1,为1的时候表示应答域有效,反之为0。
推送PSH:这个标志位表示Push操作,接收方tcp收到PSH = 1的报文段,就尽快交付给接收接收应用进程而不是再等到这个缓冲区都填满之后再向上交付。
复位RST:表示连接复位请求,当RST = 1,标明tcp有严重的错误,必须释放连接,重新建立运输连接。RST = 1还可以用来拒绝一个非法的报文段或者拒绝打开一个连接。
同步SYN:表示同步序号,用来建立连接,SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有SYN的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求一个连接严格的进行TCP的三次握手。
终止FIN: 表示发送端已经达到数据末尾,将释放一个连接,FIN = 1, 表示报文段的发送方的数据已经发送完成,请求释放连接。
窗口:占2个字节,存放的是数据是字节为单位的窗口值告诉对方,本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。这是让发送方设置发送窗口的依据。
检验和,占2个字节。
要理解三次握手,四次挥手,同步SYN、确认ACK、序号seq、确认号ack、终止FIN5个概念比较重要,下面再次加深这5个概念的理解:
同步SYN:在连接建立时用来同步序号,当SYN=1而ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1,SYN置1就表示这是一个连接请求或连接接受报文。
确认ACK:TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1。
序号seq:标识从TCP发端向TCP收端发送的数据字节流(tcp传输的每一个字节都按顺序编号),它表示在这个报文段中的的第一个数据字节在数据流中的序号。
确认号ack:确认序列号包含发送确认的一端所期望收到的下一个序号,因此,确认序号应当是上次已成功收到数据字节序号加1。不过,只有当标志位中的ACK标志为1时该确认序列号的字段才有效。
终止FIN:表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。
TCP的三次握手
- 首先是客户端发送连接请求的报文段,在该报文段头部将会设置SYN=1,表示是提出建立连接的请求,同时设置自己的一个序号为x,此时客户端进入SYN_SENT的状态。
- 当服务器端收到连接请求之后,服务器端会发送一个确认报文段,并在头部设置SYN=1,ACK=1,同时设置自己的序号为y, 确认号字段设置为x+1(表示下一次服务器端想要接收到的报文段头部序号为x+1)。发送响应报文之后服务器端进入SYN_RCVD状态。
- 最后客户端再次发送确认报文给服务器端,并在头部设置序号为x+1, 同时设置ACK=1,确认序号为y+1。之后进入ESTABLISHED状态。
- 服务器端收到客户端的确认信息之后也进入ESTABLISHED状态。
TCP的四次挥手
- 首先客户端会发送断开连接的请求,这这个请求中包含同步信号 SYN=1, FIN = 1, 同时附带自己的序号为u,发送完成之后客户端进入FIN_WAIT_1状态。
- 当服务器端收到断开连接请求之后,服务器端会发送一个响应,在这个响应中包含ACK=1,SYN=1, 同时附带自己的序号v,以及期望确认号u+1,发送完成之后,服务器端传输层需要通知应用层即将关闭连接,发送剩余数据,之后进入CLOSR_WAIT状态。
- 当客户端接收到服务器端发送回来的响应后,客户端进入FIN_WAIT_2状态。
- 当服务器端应用层处理结束之后会同时服务器端传输层断开连接,此时发送断开连接请求,包含FIN=1, SYN= 1, 以及自己的序号w, 和确认序号 u+1(因为在发送之前还没有收到序u号u之后的报文段),发送完成之后进入LAST_ACK状态。
- 当客户端收到来自服务器端的断开连接请求之后,会发送响应报文段其中包含的信息有:ACK=1, 序号为u+1,确认序号为 w+1,发送完毕之后,客户端需要等待两个MSL(最大段生存时间)。之后进入CLOSED状态。
- 服务器端收到响应报文之后进入CLOSED状态。
