TCP 连接中的TIME_WAIT
原文:http://blog.csdn.net/wangpengqi/article/details/17245349
這就有個細節,一次http請求,誰會先斷開TCP連接?什么情況下客戶端先斷,什么情況下服務端先斷?
百度后,找到原因,主要有http1.0和http1.1之間保持連接的差異以及http頭中connection、content-length、Transfer-encoding等參數有關;
?
當然,在nginx中,對于http1.0與http1.1也是支持長連接的。什么是長連接呢?我們知道,http請求是基于TCP協議之上的,那么,當客戶端在發起請求前,需要先與服務端建立TCP連接,而每一次的TCP連接是需要三次握手來確定的,如果客戶端與服務端之間網絡差一點,這三次交互消費的時間會比較多,而且三次交互也會帶來網絡流量。當然,當連接斷開后,也會有四次的交互,當然對用戶體驗來說就不重要了。而http請求是請求應答式的,如果我們能知道每個請求頭與響應體的長度,那么我們是可以在一個連接上面執行多個請求的,這就是所謂的長連接,但前提條件是我們先得確定請求頭與響應體的長度。對于請求來說,如果當前請求需要有body,如POST請求,那么nginx就需要客戶端在請求頭中指定content-length來表明body的大小,否則返回400錯誤。也就是說,請求體的長度是確定的,那么響應體的長度呢?先來看看http協議中關于響應body長度的確定:
從上面,我們可以看到,除了http1.0不帶content-length以及http1.1非chunked不帶content-length外,body的長度是可知的。此時,當服務端在輸出完body之后,會可以考慮使用長連接。能否使用長連接,也是有條件限制的。如果客戶端的請求頭中的connection為close,則表示客戶端需要關掉長連接,如果為keep-alive,則客戶端需要打開長連接,如果客戶端的請求中沒有connection這個頭,那么根據協議,如果是http1.0,則默認為close,如果是http1.1,則默認為keep-alive。如果結果為keepalive,那么,nginx在輸出完響應體后,會設置當前連接的keepalive屬性,然后等待客戶端下一次請求。當然,nginx不可能一直等待下去,如果客戶端一直不發數據過來,豈不是一直占用這個連接?所以當nginx設置了keepalive等待下一次的請求時,同時也會設置一個最大等待時間,這個時間是通過選項keepalive_timeout來配置的,如果配置為0,則表示關掉keepalive,此時,http版本無論是1.1還是1.0,客戶端的connection不管是close還是keepalive,都會強制為close。
如果服務端最后的決定是keepalive打開,那么在響應的http頭里面,也會包含有connection頭域,其值是”Keep-Alive”,否則就是”Close”。如果connection值為close,那么在nginx響應完數據后,會主動關掉連接。所以,對于請求量比較大的nginx來說,關掉keepalive最后會產生比較多的time-wait狀態的socket。一般來說,當客戶端的一次訪問,需要多次訪問同一個server時,打開keepalive的優勢非常大,比如圖片服務器,通常一個網頁會包含很多個圖片。打開keepalive也會大量減少time-wait的數量。
——————————————————————————————————————————————————————————————————————————
TIME_WAIT是什么?
從下圖可以看出: TIME_WAIT 產生在主動斷開連接的一方
在TCP斷開的過程中會有四個狀態變化過程,如下圖所示:
在連接撤銷過程中,有如下過程:?????????????????????????????????????????? 1.HOST1上的應用程序關閉己方的連接導致TCP發送一個FIN消息給HOST2。 2.HOST2發送一個確認消息給HOST1,并且HOST2把FIN作為EOF遞交給HOST2上的應用程序。 3.一段時間過后,HOST2上的應用程序關閉它那邊的連接,引發一個FIN消息給HOST1。 4.HOST1給HOST2發送一個確認消息,然后HOST2關閉連接并釋放資源,然而,HOST1卻沒有關閉連接,而是進入了TIME_WAIT狀態,并為兩個最大段生存時間(2MSL)保留在此狀態. 為什么需要TIME_WAIT? 1.因為在第四步的時候,HOST1發送的ACK可能丟失并導致HOST2重新發送FIN消息,TIME_WAIT維護連接狀態. 如果執行主動關閉的一方HOST1 不進入到TIME_WAIT狀態就關閉連接那會發生什么呢?當重傳的FIN消息到達時,因為TCP已經不再有連接的信息了,所以就用RST(重新啟動)消息應答,導致HOST2進入錯誤的狀態而不是有序終止狀態,如果發送最后ACK消息的一方處于TIME_WAIT狀態并仍然記錄著連接的信息,它就可以正確的響應對等方HOST2的FIN消息了. 2.TIME_WAIT為連接中”離群的段”提供從網絡中消失的時間. 考慮一下,如果延遲或者重傳段在連接關閉后到達時會發生什么呢?通常情況下,因為TCP僅僅丟棄該數據并響應RST消息,所以這不會造成任何問題。當RST消息到達發出延時段的主機時,因為該主機也沒有記錄連接的任何信息,所以它也丟棄該段。然而,如果兩個相同主機之間又建立了一個具有相同端口號的新連接,那么離群的段就可能被看成是新連接的,如果離群的段中數據的任何序列號恰恰在新連接的當前接收窗口中,數據就會被重新接收,其結果就是破壞新連接轉載于:https://www.cnblogs.com/oxspirt/p/6054931.html
總結
以上是生活随笔為你收集整理的TCP 连接中的TIME_WAIT的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c#通过app.manifest使程序以
- 下一篇: Halcon:区域特征:select_s