TCP四次揮手中如果服務(wù)端沒收到第四次揮手請求,服務(wù)端會一直等待嗎?
搬運(yùn)一個在某乎的回答,水一篇文章吧。
TCP四次揮手
正常情況下。只要數(shù)據(jù)傳輸完了,不管是客戶端還是服務(wù)端,都可以主動發(fā)起四次揮手,釋放連接。
就跟上圖畫的一樣,假設(shè),這次四次揮手是由客戶端主動發(fā)起的,那它就是主動方。服務(wù)器是被動接收客戶端的揮手請求的,叫被動方。
客戶端和服務(wù)器,一開始,都是處于ESTABLISHED狀態(tài)。
- 第一次揮手:一般情況下,主動方執(zhí)行close()?或 shutdown()?方法,會發(fā)個FIN報文出來,表示"我不再發(fā)送數(shù)據(jù)了"。
- 第二次揮手:在收到主動方的FIN?報文后,被動方立馬回應(yīng)一個ACK,意思是"我收到你的FIN了,也知道你不再發(fā)數(shù)據(jù)了"。
上面提到的是主動方不再發(fā)送數(shù)據(jù)了。但如果這時候,被動方還有數(shù)據(jù)要發(fā),那就繼續(xù)發(fā)。注意,雖然第二次和第三次揮手之間,被動方是能發(fā)數(shù)據(jù)到主動方的,但主動方能不能正常收就不一定了,這個待會說。
- 第三次揮手:在被動方在感知到第二次揮手之后,會做了一系列的收尾工作,最后也調(diào)用一個 close()?, 這時候就會發(fā)出第三次揮手的 FIN-ACK。
- 第四次揮手:主動方回一個ACK,意思是收到了。
其中第一次揮手和第三次揮手,都是我們在應(yīng)用程序中主動觸發(fā)的(比如調(diào)用close()方法),也就是我們平時寫代碼需要關(guān)注的地方。
第二和第四次揮手,都是內(nèi)核協(xié)議棧自動幫我們完成的,我們寫代碼的時候碰不到這地方,因此也不需要太關(guān)心。
另外不管是主動還是被動,每方發(fā)出了一個 FIN? 和一個ACK? 。也收到了一個 FIN? 和一個ACK 。
回到題主的問題。
TCP四次揮手中如果服務(wù)端沒收到第四次揮手請求,服務(wù)端會一直等待嗎?
第四次揮手是第三次揮手觸發(fā)的。如果第四次揮手服務(wù)端一直沒收到,那服務(wù)端會認(rèn)為是不是自己的第三次揮手丟了,于是服務(wù)端不斷重試發(fā)第三次揮手(FIN).重發(fā)次數(shù)由系統(tǒng)的tcp_orphan_retries參數(shù)控制。重試多次還沒成功,服務(wù)端直接斷開鏈接。所以結(jié)論是服務(wù)端不會一直等待第四次揮手。
TCP第四次揮手丟失
# cat /proc/sys/net/ipv4/tcp_orphan_retries
0
另外,你會發(fā)現(xiàn)tcp_orphan_retries參數(shù)是0,但其實并不是不重試的意思。為0時,默認(rèn)值為8. 也就是重試8次。
/* Calculate maximal number or retries on an orphaned socket. */
static int tcp_orphan_retries(struct sock *sk, int alive)
{
int retries = sysctl_tcp_orphan_retries; /* May be zero. */
/* We know from an ICMP that something is wrong. */
if (sk->sk_err_soft && !alive)
retries = 0;
/* However, if socket sent something recently, select some safe
* number of retries. 8 corresponds to >100 seconds with minimal
* RTO of 200msec. */
if (retries == 0 && alive)
retries = 8;
return retries;
}
當(dāng)然如果服務(wù)端重試發(fā)第三次揮手FIN的過程中,還是同樣的端口和IP,起了個新的客戶端,這時候服務(wù)端重試的FIN被收到后,客戶端就會認(rèn)為是不正常的數(shù)據(jù)包,直接發(fā)個RST給服務(wù)端,這時候兩端連接也會斷開。