tcp 資料傳輸過程圖
參考:執行服務端(為每個客戶端fork子程序服務) 和 乙個客戶端,可以看到 服務端的父程序和子程序
如下圖,找到服務端子程序的pid, 直接kill掉
kill 子程序後,子程序相關的開啟描述符都會被關閉,這就導致向客戶端傳送乙個fin, 而客戶tcp則響應以乙個ack, 這是tcp連線終止(四次握手)的前半部分。
在服務端,設定了程序kill掉的訊號,當$kill後,會立即看到
signal傳送給服務端父程序,得到正確處理(可以看到child terminated 被列印出來)
服務端主動關閉連線,會向客戶端傳送乙個fin, 客戶端接收來自服務端的fin並響應乙個ack, 但自己是阻塞在fgets呼叫上,此時客戶端還沒有傳送fin。
john@ubuntu
:~$ netstat -a | grep 9877
tcp 0
0 *:
9877 *:*
listen
tcp 0
0localhost:
9877
localhost:
59644
fin_wait2
tcp 1
0localhost:
59644
localhost:
9877
close_wait
服務端子程序 fin_wait2(主動關閉的一方收到對方的ack後,等待對方傳送fin)
客戶端 close_wait (被動關閉的一方,傳送了fin後處於 close_wait 狀態,等待關閉連線)
客戶端仍在執行阻塞在fgets上,我們接著輸入一段文字,給服務端,發現接收不到任何結果了
sudo tcpdump -i lo # tcpdump檢視資料報
在完成tcp結束連線(四次握手)的前半部分後,客戶端可以繼續傳送資料(而此時服務端已經結束)因為客戶端收到服務端傳送過來的fin後,服務端並沒有告訴客戶端自己已經終止了, 所以客戶端可以傳送資料,只是得不到響應而已。
所以我們想要的是:一旦伺服器程序死掉了,客戶端應該立刻收到fin,並且自己不再傳送資料
服務端和客戶端成功連線,能相互傳送資料,此時若伺服器突然不可達(如網路中斷了)。這時客戶端傳送資料,將阻塞在read呼叫(一直等待服務端應答。。。)上。
客戶tcp持續重傳資料分節,源自berkeley的實現重傳該資料分節12次,共等待約9分鐘後,才放棄重傳。
客戶端最終知道 伺服器不可達,顯然9分鐘比較長,我們可以在read呼叫設定乙個超時。
當然如果客戶端沒有給伺服器傳送資料,怎麼知道伺服器已經不可達了呢?so_keepalive套接字?
unix系統關機 會產生訊號,伺服器主機會關閉其所有開啟描述符,其所有子程序也將關閉。這樣之後的情況將如同tcp伺服器程序突然終止一樣,我們仍然需要使得伺服器程序的終止一旦發生,客戶端能夠立刻檢測到
關閉tcp連線
luolei localhost sudo netstat a grep ssh tcp 0 0 192.168.1.10 40278 com ssh established unix 2 acc stream listening 7565 tmp ssh uyvolk4882 agent.4882...
TCP長短連線
tcp 長短連線 1 什麼是 tcp長連線 從應用層來看,就是 client 到server 建立一次連線,傳送多個資料報,直到不再與 server 通訊時關閉連線。connect send recv send recv close。從傳輸層來看,使用的是 keep alive timer 實現 t...
Tcp 斷開連線
tcp協議規定,對於已經建立的連線,網路雙方要進行四次握手才能成功斷開連線,如果缺少了其中某個步驟,將會使連線處於假死狀態,連線本身占用的資源不會被釋放。網路伺服器程式要同時管理大量連線,所以很有必要保證無用連線完全斷開,否則大量僵死的連線會浪費許多伺服器資源。在眾多tcp狀態中,最值得注意的狀態有...