TCP三次握手与四次挥手
TCP三次握手
-
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers);
-
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
-
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。
TCP四次挥手
-
客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送;
-
服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号;
-
服务器B关闭与客户端A的连接,发送一个FIN给客户端A;
-
客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
TCP报文
- 序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
- 确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
tcp的6种标志位的分别代表
标志位 | 全称 | 含义 |
---|---|---|
SYN | synchronous | 发起一个新连接 |
ACK | acknowledgement | 确认序号有效 |
PSH | push | 接收方应该尽快将这个报文交给应用层 |
FIN | finish | 释放一个连接 |
RST | reset | 重置连接 |
URG | urgent | 紧急指针(urgent pointer)有效 |
不要将确认序号Ack与标志位中的ACK搞混了
握手过程具体报文内容
- 第一次握手:客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里
- 第二次握手:服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的ISN加1以,即X+1
- 第三次握手:客户端再次发送确认包(ACK)SYN标志位为0,ACK标志位为1,并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1
::: danger 为了方便查看,图片中标志位的所占字节大小与实际不符 :::
初始序列号(ISN):当两台主机需要使用TCP传输协议传输数据时,会创建一个新的连接。这涉及希望启动连接的第一个主机,以生成所谓的初始序列号(ISN),它基本上是我们正在查看的序列字段中包含的第一个序列号。
TCP状态迁移
客户端TCP状态迁移
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服务器TCP状态迁移
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
各个状态的意义如下
| 标志位 | 含义 | | --- | --- | --- | | LISTEN | 侦听来自远方TCP端口的连接请求 | | SYN-SENT | 在发送连接请求后等待匹配的连接请求; | | SYN-RECEIVED | 在收到和发送一个连接请求后等待对连接请求的确认; | | ESTABLISHED | 代表一个打开的连接,数据可以传送给用户; | | FIN-WAIT-1 | 等待远程TCP的连接中断请求,或先前的连接中断请求的确认; | | FIN-WAIT-2 | 从远程TCP等待连接中断请求; | | CLOSE-WAIT | 等待从本地用户发来的连接中断请求; | | CLOSING | 等待远程TCP对连接中断的确认; | | LAST-ACK | 等待原来发向远程TCP的连接中断请求的确认; | | TIME-WAIT | 等待足够的时间以确保远程TCP接收到连接中断请求的确认; | | CLOSED | 没有任何连接状态; |
为什么TCP链接不是两次
为了双方都能明确自己和对方的收、发能力是正常的。
-
第一次握手:客户端无法知道自己发送是否正常,但是服务端收到请求,知道客户端发送能力正常,自己服务端的接受能力正常;
-
第二次握手:服务的发送请求到客户端,客户端知道服务端接受到自己第一次握手的请求了,客户端知道自己的发送和接受能力正常,服务端的发送和接受能力正常;
-
第三次握手:服务端接收到客户端的确认消息,确认了服务端的发送,接受能力正常。
视角 | 客收 | 客发 | 服收 | 服发 |
---|---|---|---|---|
客视角 | 二 | 一 + 二 | 一 + 二 | 二 |
服视角 | 二 + 三 | 一 | 一 | 二 + 三 |
为什么TCP断开链接需要四次
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手
确认号与序列号关系
确认号:其数值等于发送方的发送序号 +1(即接收方期望接收的下一个序列号)
TCP协议如何来保证传输的可靠性
TCP提供一种面向连接的、可靠的字节流服务。其中,面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。在一个TCP连接中,仅有两方进行彼此通信;而字节流服务意味着两个应用程序通过TCP链接交换8bit字节构成的字节流,TCP不在字节流中插入记录标识符。
对于可靠性,TCP通过以下方式进行保证
-
数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时TCP发送数据端超时后会重发数据;
-
对失序数据包重排序:既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序,然后才交给应用层;
-
丢弃重复数据:对于重复数据,能够丢弃重复数据;
-
应答机制:当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
-
超时重发:当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
-
流量控制:TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP使用的流量控制协议是可变大小的滑动窗口协议。