TCP建立连接的三次握手
客户端
- ①[CLOSED -> SYN_SENT] 客户端调用connect, 发送同步报文段;
- ③[SYN_SENT -> ESTABLISHED] 接收到服务器端发送的SYN报文,并向服务器端发送SYN确认报文。此时connect调用成功, 则进入ESTABLISHED状态, 开始读写数据;
服务器端
- ①[CLOSED -> LISTEN] 服务器端调用listen后进入LISTEN(监听)状态, 等待客户端连接;
- ②[LISTEN -> SYN_RCVD] 一旦监听到连接请求(同步报文段), 就将该连接放入内核等待队列中, 并向客户端发送SYN确认报文。
- ④[SYN_RCVD -> ESTAB_LISHED] 服务端一旦收到客户端的确认报文, 就进入ESTABLISHED状态, 可以进行读写数据了。
TCP断开连接的四次挥手
客户端(主动断开方)
- ①[ESTABLISHED -> FIN_WAIT_1] 客户端主动调用close时, 向服务器发送结束报文段, 同时进入FIN_WAIT_1状态;
- ③[FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认, 则进入FIN_WAIT_2, 开始等待服务器的结束报文段;
- ⑤[FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出LAST_ACK,意为同意结束;
-⑥[TIME_WAIT -> CLOSED] 客户端要等待一个2MSL(报文最大生存时间)的时间, 才会进入CLOSED状态.
服务器端(被动断开方)
- ②[ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调用close)时, 服务器会收到结束报文段, 服务器返回确认报文段并进入CLOSE_WAIT;
- ④[CLOSE_WAIT -> LAST_ACK] 进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据); 当服务器真正调用close关闭连接时, 会向客户端发送FIN, 此时服务器进入LAST_ACK状态, 等待最后一个ACK到来(这个ACK是客户端确认收到了FIN)。
- ⑥[LAST_ACK -> CLOSED] 服务器收到了对FIN的ACK,彻底关闭连接。
面试考点
1、为什么是三次握手,两次可以吗?
- 首先,两次是不可以的。
- 当客户端发出的第一个连接请求报文段长时间没有被服务器接收时,它并没有丢失,而是在某个网络结点长时间的滞留,所以延误到连接释放后的某个时间才到达服务器端。本来这是一个早已失效的连接请求报文段。但服务器收到此失效的连接请求报文段后,就误认为是客户端再次发出的一个新的连接请求。于是就向客户端发出确认报文段,同意建立连接。
- 假设不采用“三次握手”,那么只要服务器端发出确认,新的连接就建立了。但是现在客户端并没有发出建立连接的请求,因此不会处理服务器端的确认,也不会向服务器端发送数据。但服务器端却以为新的连接已经建立,并一直等待客户端发来数据。这样,就会造成服务器端资源浪费。
- 采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,如果client 接收到server 的确认报文段后,没有向server 发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。
- 主要目的防止 server 端一直等待,浪费资源。
2、为什么挥手一般是四次?挥手在某些情况下三次能完成吗?
某些情况下,三次是可以完成挥手的,当本端关闭了连接,恰好也同时收到了对方的 FIN 报文,此时可以把自己的 FIN 和给对端的确认 ACK 合在一起发送,就变成了三次。
3、三次握手那个阶段容易出现攻击?
- 比较典型的是 syn 泛洪攻击(syn 溢出攻击)。
- syn 溢出攻击会出现在第二个阶段,如果客户机伪造出大量第一次的 syn 同步报文,服务端就会依次耗掉很多资源来保存客户端的信息,并回复大量的确认报文段,实际确认是会失败的,但失败是需要一定时间,因为服务端会连续多次进行第二次握手确认后才认定失败。那么短时间服务器会接收到大量 syn 同步报文,服务器资源可能会被耗尽,就可能导致正常的客户端得不到响应而失败。
4、三次握手的作用是:
(1) 使得通讯双发都做好通讯的准备
(2) 告诉对端本端通讯所选用的报文标识号
(3) 防止已失效的连接请求报文段又突然传递到了服务端,从而产生错误
5、TIME_WAIT 状态存在的意义?
- TIME_WAIT 状态是主动断开连接的一端收到对端的 FIN 报文段并且将 ACK 报文段发出后的一种状态。
- 意义:
(1)保证最后一个ACK能够发送给被动断开方,如果没有到,则被动断开方会重传FIN,主动段开方能够处理重传的FIN (主动断开方能够重传最后的ACK)。即保证可靠的终止TCP连接
(2)保证迟来的数据报文段能够被识别并丢弃,从而不会对后面的连接产生影响。
6、TIME_WAIT 和 CLOSE_WAIT 有什么区别?
- CLOSE_WAIT 是被动关闭的一端在接收到对端关闭请求(FIN 报文段)并且将 ACK发送出去后所处的状态,这种状态表示收到了对端关闭的请求,但是本端还没有完成工作,还未关闭。
- TIME_WAIT 状态是主动关闭的一端在本端已经关闭的前期下,收到对端的关闭请求(FIN 报文段)并且将 ACK 发送出去后所处的状态,这种状态表示:双方都已经完成工作,只是为了确保迟来的数据报能被是被并丢弃,可靠的终止 TCP 连接。