偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

字節(jié)一面:TCP 三次握手,問的好細(xì)!

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
TCP 三次握手中,客戶端收到的第二次握手中 ack 確認(rèn)號(hào)不是自己期望的,會(huì)發(fā)生什么?是直接丟棄 or 回 RST 報(bào)文?

大家好,我是小林。

有位讀者在面試字節(jié)時(shí),被問到這么個(gè)問題:

圖片

概括起來(lái),是這兩個(gè)問題:

TCP 三次握手中,客戶端收到的第二次握手中 ack 確認(rèn)號(hào)不是自己期望的,會(huì)發(fā)生什么?是直接丟棄 or 回 RST 報(bào)文?

什么情況下會(huì)收到不正確的 ack(第二次握手中的 ack) 呢?

問題解答

不賣關(guān)子,直接說(shuō)這個(gè)問題,是回 RST 報(bào)文。過(guò)程如下圖:

圖片

三次握手避免歷史連接

當(dāng)客戶端連續(xù)發(fā)送多次建立連接的 SYN 報(bào)文,然后在網(wǎng)絡(luò)擁堵的情況,就會(huì)發(fā)生客戶端收到不正確的 ack 的情況。具體過(guò)程如下:

  • 客戶端先發(fā)送了 SYN(seq = 90) 報(bào)文,但是被網(wǎng)絡(luò)阻塞了,服務(wù)端并沒有收到,接著客戶端又重新發(fā)送了 SYN(seq = 100) 報(bào)文,注意不是重傳 SYN,重傳的 SYN 的序列號(hào)是一樣的。
  • 「舊 SYN 報(bào)文」比「最新的 SYN 」 報(bào)文早到達(dá)了服務(wù)端,那么此時(shí)服務(wù)端就會(huì)回一個(gè) SYN + ACK 報(bào)文給客戶端,此報(bào)文的確認(rèn)號(hào)是 91(90+1)。
  • 客戶端收到后,發(fā)行自己期望收到的確認(rèn)號(hào)應(yīng)該是 100+1,而不是 90 + 1,于是就會(huì)回 RST 報(bào)文。
  • 服務(wù)端收到 RST 報(bào)文后,就會(huì)中止連接。
  • 后續(xù)最新的 SYN 抵達(dá)了服務(wù)端后,客戶端與服務(wù)端就可以正常的完成三次握手了。

上述中的「舊 SYN 報(bào)文」稱為歷史連接,TCP 使用三次握手建立連接的最主要原因就是防止「歷史連接」初始化了連接。

我們也可以從 RFC 793 知道 TCP 連接使用三次握手的首要原因:

The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

簡(jiǎn)單來(lái)說(shuō),三次握手的首要原因是為了防止舊的重復(fù)連接初始化造成混亂。RFC 給出的三次握手防止歷史連接的案例圖如下:

圖片

RFC 793

如果是兩次握手連接,就無(wú)法阻止歷史連接,那為什么 TCP 兩次握手為什么無(wú)法阻止歷史連接呢?

我先直接說(shuō)結(jié)論,主要是因?yàn)樵趦纱挝帐值那闆r下,「被動(dòng)發(fā)起方」沒有中間狀態(tài)給「主動(dòng)發(fā)起方」來(lái)阻止歷史連接,導(dǎo)致「被動(dòng)發(fā)起方」可能建立一個(gè)歷史連接,造成資源浪費(fèi)。

你想想,兩次握手的情況下,「被動(dòng)發(fā)起方」在收到 SYN 報(bào)文后,就進(jìn)入 ESTABLISHED 狀態(tài),意味著這時(shí)可以給對(duì)方發(fā)送數(shù)據(jù)給,但是「主動(dòng)發(fā)」起方此時(shí)還沒有進(jìn)入 ESTABLISHED 狀態(tài),假設(shè)這次是歷史連接,主動(dòng)發(fā)起方判斷到此次連接為歷史連接,那么就會(huì)回 RST 報(bào)文來(lái)斷開連接,而「被動(dòng)發(fā)起方」在第一次握手的時(shí)候就進(jìn)入 ESTABLISHED 狀態(tài),所以它可以發(fā)送數(shù)據(jù)的,但是它并不知道這個(gè)是歷史連接,它只有在收到 RST 報(bào)文后,才會(huì)斷開連接。

圖片

兩次握手無(wú)法阻止歷史連接

可以看到,上面這種場(chǎng)景下,「被動(dòng)發(fā)起方」在向「主動(dòng)發(fā)起方」發(fā)送數(shù)據(jù)前,并沒有阻止掉歷史連接,導(dǎo)致「被動(dòng)發(fā)起方」建立了一個(gè)歷史連接,又白白發(fā)送了數(shù)據(jù),妥妥地浪費(fèi)了「被動(dòng)發(fā)起方」的資源。

因此,要解決這種現(xiàn)象,最好就是在「被動(dòng)發(fā)起方」發(fā)送數(shù)據(jù)前,也就是建立連接之前,要阻止掉歷史連接,這樣就不會(huì)造成資源浪費(fèi),而要實(shí)現(xiàn)這個(gè)功能,就需要三次握手。

源碼分析

我說(shuō)回 RST 就回 RST 嗎?當(dāng)然不是了,肯定得用源碼證明我說(shuō)的這個(gè)結(jié)論。

聽到要源碼分析,可能有的同學(xué)就慫了。

其實(shí)要分析我們今天這個(gè)問題,只要懂 if else 就行了,我也會(huì)用中文來(lái)表述代碼的邏輯,所以單純看我的文字也是可以的。

這次我們重點(diǎn)分析的是,在 SYN_SENT 狀態(tài)下,收到不正確的確認(rèn)號(hào)的 syn+ack 報(bào)文是如何處理的。

處于 SYN_SENT 狀態(tài)下的客戶端,在收到服務(wù)端的  syn+ack 報(bào)文后,最終會(huì)調(diào)用  tcp_rcv_state_process,在這里會(huì)根據(jù) TCP 狀態(tài)做對(duì)應(yīng)的處理,這里我們只關(guān)注 SYN_SENT 狀態(tài)。

// net/ipv4/tcp_ipv4.c
int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
{
...

int queued = 0;

...

switch (sk->sk_state) {
case TCP_CLOSE:
...
case TCP_LISTEN:
...
case TCP_SYN_SENT:
....
queued = tcp_rcv_synsent_state_process(sk, skb, th);
if (queued >= 0)
return queued;
...
}

可以看到,接下來(lái),會(huì)繼續(xù)調(diào)用 tcp_rcv_synsent_state_process 函數(shù)。

static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th)
{
....

if (th->ack) {
/* rfc793:
* "If the state is SYN-SENT then
* first check the ACK bit
* If the ACK bit is set
* If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send
* a reset (unless the RST bit is set, if so drop
* the segment and return)"
*/
// ack 的確認(rèn)號(hào)不是預(yù)期的
if (!after(TCP_SKB_CB(skb)->ack_seq, tp->snd_una) ||
after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt))
//回 RST 報(bào)文
goto reset_and_undo;

...
}

從上面的函數(shù),就可以得知了,客戶端在 SYN_SENT 狀態(tài)下,收到不正確的確認(rèn)號(hào)的 syn+ack 報(bào)文會(huì)回 RST 報(bào)文。

小結(jié)

TCP 三次握手中,客戶端收到的第二次握手中 ack 確認(rèn)號(hào)不是自己期望的,會(huì)發(fā)生什么?是直接丟棄 or 回 RST 報(bào)文?

回 RST 報(bào)文。

什么情況下會(huì)收到不正確的 ack(第二次握手中的 ack) 呢?

當(dāng)客戶端發(fā)起多次 SYN 報(bào)文,然后網(wǎng)絡(luò)擁堵的情況下,「舊的 SYN 報(bào)文」比「新的 SYN 報(bào)文」早抵達(dá)服務(wù)端,此時(shí)服務(wù)端就會(huì)按照收到的「舊的 SYN 報(bào)文」回復(fù) syn+ack 報(bào)文,而此報(bào)文的確認(rèn)號(hào)并不是客戶端期望收到的,于是客戶端就會(huì)回 RST 報(bào)文。

責(zé)任編輯:武曉燕 來(lái)源: 小林coding
相關(guān)推薦

2024-08-27 09:05:45

2023-09-07 16:46:54

TCP數(shù)據(jù)傳遞

2020-12-08 06:34:16

TCP握手SYN 報(bào)文

2015-10-13 09:42:52

TCP網(wǎng)絡(luò)協(xié)議

2024-01-12 08:23:11

TCPACK服務(wù)器

2023-10-24 15:22:09

TCPUDP

2024-10-09 20:54:16

2022-07-07 09:00:17

TCP 連接HTTP 協(xié)議

2022-10-10 07:34:36

TCP三次握手區(qū)塊鏈

2021-05-18 12:27:40

TCP控制協(xié)議

2021-01-29 06:11:08

TCP通信三次握手

2019-06-12 11:26:37

TCP三次握手四次揮手

2022-08-28 20:35:52

三次握手四次揮手TCP

2022-07-25 07:07:35

TCP客戶端服務(wù)器

2021-03-08 18:08:08

TCP Connect 協(xié)議

2019-12-12 10:36:43

TCPSYNIP

2023-09-02 21:57:52

網(wǎng)絡(luò)TCP協(xié)議

2018-10-15 08:06:33

TCP握手原理

2020-08-27 07:41:28

TCP協(xié)議數(shù)據(jù)

2018-07-05 14:25:01

TCP握手原理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)