TCP 是支持全雙工通訊的傳輸層協議,爲了開發出更好的網絡通訊應用,清楚瞭解其中的交互過程是很是必要的。html
下面用比較直白的話來描述&理解一下這個過程:編程
TCP 鏈接創建:三次握手服務器
服務器依次調用 socket,bind,linsten 綁定到指定本機地址,accept 阻塞等待鏈接。網絡
1. 客戶端調用 socket 指定本地/網絡地址,connect 主動創建鏈接,向服務器發送 SYN 同步請求,並標記該鏈接通道傳送數據的初始序號爲 J 。socket
2. 服務器收到 SYN 請求後,響應 ACK(acknowledgement)確認收到,並標記序號爲 J + 1 ;tcp
同時服務器也向客戶端發送一個 SYN 同步請求,並標記該鏈接通道傳送數據的初始序號爲 K 。htm
3. 客戶端收到 SYN 請求後,對服務器響應 ACK 確認收到,並標記序號爲 K + 1 。blog
在完成上面三步以後,TCP鏈接完成,客戶與服務器之間能夠互發數據了。開發
TCP 鏈接終止:四次揮手get
客戶或服務器均可以主動發起 close 動做。
1. 客戶調用 close 主動關閉鏈接,此時向服務器發送 FIN(finish)請求,標記鏈接的數據序號爲 M 。
2. 服務器收到客戶結束請求後,響應 ACK 確認,並標記鏈接數據序號爲 M + 1 。
3. 服務器被動關閉,向客戶發送 FIN 請求,標記鏈接的數據序號爲 N 。
4. 客戶收到服務器的 FIN 請求後,響應 ACK 確認,並標記鏈接的數據序號爲 N + 1 。
完成上面四步,TCP鏈接終止。
TCP鏈接的分組交換
TCP 的 SO_KEEPALIVE 套接字選項
這是一個檢測鏈接存活的選項,設置了 keep-alive 選項後,若是 2小時內在該套接字的任一方向上都沒有數據交換,
TCP 就自動給對端發送一個保持存活探測分節(keep-alive probe),這是一個對端必須響應的 TCP 分節。
若是沒有對 TCP 探測分節的響應,套接字待處理錯誤被置爲 TIMEOUT,套接字關閉。
HTTP 的 keep-alive 屬性
HTTP 是基於 TCP 之上的無狀態的請求-響應式短鏈接,每個請求就是一個 TCP 鏈接,頻繁的三次握手和四次揮手會浪費傳輸以外的大量時間。
爲了提升鏈接和應用效率,服務端設置 keep-alive 後客戶端在發起一次請求後,服務器端不會立刻關閉這個 TCP 鏈接,而是在一段時間內等待,有數據傳輸就複用這個鏈接。
@todo 用 tcpdump 分析鏈接的過程。
參考文獻:
Unix網絡編程1 > 傳輸層:TCP、UDP、SCTP > TCP鏈接的創建和終止
Unix網絡編程1 > 套接字選項 > 通用套接字選項