socket是什麼呢?
socket是應用層與tcp/ip協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,socket其實就是乙個門面模式,它把複雜的tcp/ip協議族隱藏在socket介面後面,對使用者來說,一組簡單的介面就是全部,讓socket去組織資料,以符合指定的協議。不過socket在不同的語境中有不同的含義,如再說tcp連線的倆個端點時,socket的含義是套接字,socket=ip:port。我們本次主要討論的是,socket作為一組介面的含義。
應用層使用socket介面進行程序間的通訊,一般我們會將主動接收訊息的一端稱為伺服器端,主動傳送訊息的一端稱為客戶端。先從伺服器端說起。伺服器端先初始化socket,然後與埠繫結(bind),對埠進行監聽(listen),呼叫accept阻塞,等待客戶端連線。在這時如果有個客戶端初始化乙個socket,然後連線伺服器(connect),如果連線成功,這時客戶端與伺服器端的連線就建立了。客戶端傳送資料請求,伺服器端接收請求並處理請求,然後把回應資料傳送給客戶端,客戶端讀取資料,最後關閉連線,一次互動結束。
socket 客戶端與伺服器段進行連線與釋放鏈結要經過三次握手和四次揮手,以下基於tcp三次握手建立連線、四次揮手斷開連線進行詳解。
tcp報文首部內容:
位碼即tcp標誌位,有6種標示:
syn(synchronous建立聯機)
ack(acknowledgement 確認)
psh(push傳送)
fin(finish結束)
rst(reset重置)
urg(urgent緊急)
sequence number(順序號碼)
acknowledge number(確認號碼)
名詞詳解:
序列號seq:佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生;給位元組編上序號後,就給每乙個報文段指派乙個序號;序列號seq就是這個報文段中的第乙個位元組的資料編號。
確認號ack:佔4個位元組,期待收到對方下乙個報文段的第乙個資料位元組的序號;序列號表示報文段攜帶資料的第乙個位元組的編號;而確認號指的是期望接收到下乙個位元組的編號;因此當前報文段最後乙個位元組的編號+1即為確認號。
確認ack:佔1位,僅當ack=1時,確認號字段才有效。ack=0時,確認號無效
同步syn:連線建立時用於同步序號。當syn=1,ack=0時表示:這是乙個連線請求報文段。若同意連線,則在響應報文段中使得syn=1,ack=1。因此,syn=1表示這是乙個連線請求,或連線接受報文。syn這個標誌位只有在tcp建立連線時才會被置1,握手完成後syn標誌位被置0。
終止fin:用來釋放乙個連線。fin=1表示:此報文段的傳送方的資料已經傳送完畢,並要求釋放運輸連線
ps:ack、syn和fin這些大寫的單詞表示標誌位,其值要麼是1,要麼是0;ack、seq小寫的單詞表示序號。
tcp三次握手
所謂三次握手(three-way handshake),是指建立乙個tcp連線時,需要客戶端和伺服器總共傳送3個包即互動三次。
三次握手的目的是確認互動雙方的活動狀態。在socket程式設計中,客戶端執行connect()時。將觸發三次握手。
1、 第一次,有客戶端呼叫connect 觸發。客戶端傳送乙個報文,其中syn=1,代表本次請求建立連線,同時傳送了乙個序列號seq = x。
2、 第二次,伺服器端接收到客戶端的請求,返回乙個確認包。確認包包含 (syn=1,akc=1),表示服務端請求與客戶端連線。ack(確認號碼)的值為客戶端請求的序列號+1。同時也傳送乙個序列號給客戶端。此時客戶端收到通知後,已經知道了伺服器端可以正常接收和傳送訊息。但是伺服器端並不知道客戶端是否可以正常接收訊息。所有就需要第三次握手。
3、 第三次,客戶端向伺服器端返回乙個確認包(ack=1),其中確認號碼ack為伺服器端傳送的序列號碼+1和乙個序列號z。伺服器接收到後可以確認客戶端有接收能力。此時,雙方已經確認對方都具有傳送和接收的能力,客戶端和伺服器已經完成了雙向連線的建立。
客戶端的connect在三次握手的第二個次返回,而伺服器端的accept在三次握手的第三次返回。
ps:注意字母大小寫不同表示的含義不同
tcp 四次揮手
tcp的連線的拆除需要傳送四個包即四次互動,因此稱為四次揮手(four-way handshake)。客戶端或伺服器均可主動發起揮手動作,在socket程式設計中,任何一方執行close()操作即可產生揮手操作。
由於tcp連線是全雙工通訊的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料傳送任務後就能傳送乙個fin來終止這個方向的連線。收到乙個 fin只意味著這一方向上沒有資料流動,乙個tcp連線在收到乙個fin後仍能傳送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
客戶端主動關閉連線,之後伺服器端關閉連線:
1、 客戶端程序發出連線釋放報文,並且停止傳送資料。釋放資料報文首部,fin=1,其序列號為seq=u(等於前面已經傳送過來的資料的最後乙個位元組的序號加1),此時,客戶端進入fin-wait-1(終止等待1)狀態。 tcp規定,fin報文段即使不攜帶資料,也要消耗乙個序號。
2、 伺服器收到連線釋放報文,發出確認報文,ack=1,ack=u+1,並且帶上自己的序列號seq=v,此時,服務端就進入了close-wait(關閉等待)狀態。tcp伺服器通知高層的應用程序,客戶端向伺服器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有資料要傳送了,但是伺服器若傳送資料,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個close-wait狀態持續的時間。
3、 客戶端收到伺服器的確認請求後,此時,客戶端就進入fin-wait-2(終止等待2)狀態,等待伺服器傳送連線釋放報文(在這之前還需要接受伺服器傳送的最後的資料)。
4、 伺服器將最後的資料傳送完畢後,就向客戶端傳送連線釋放報文,fin=1,ack=u+1,由於在半關閉狀態,伺服器很可能又傳送了一些資料,假定此時的序列號為seq=w,此時,伺服器就進入了last-ack(最後確認)狀態,等待客戶端的確認。
5、 客戶端收到伺服器的連線釋放報文後,必須發出確認,ack=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了time-wait(時間等待)狀態。注意此時tcp連線還沒有釋放,必須經過2∗∗msl(最長報文段壽命)的時間後,當客戶端撤銷相應的tcb後,才進入closed狀態。
5.1 、 客戶端為什麼要等待2msl
客戶端返回最後的確認包,伺服器端接收到確認包後進入關閉狀態。但是確認包有可能丟失,如果伺服器端長時間沒有收到確認,會觸發超時重傳機制,所以在2msl的時間段內,客戶端必須還具有接收能力。這也是為什麼客戶端請求的時候不需要指定自身的埠,因為這個埠會被占用一端時間,如果再次發起請求,就回出現埠被占用的情況,所以使用隨機埠。
6、 伺服器只要收到了客戶端發出的確認,立即進入closed狀態。同樣,撤銷tcb後,就結束了這次的tcp連線。可以看到,伺服器結束tcp連線的時間要比客戶端早一些。
抓包樣例:
tcp還設有乙個保活計時器,顯然,客戶端如果出現故障,伺服器不能一直等下去,白白浪費資源。伺服器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到客戶端的任何資料,伺服器就會傳送乙個探測報文段,以後每隔75分鐘傳送一次。若一連傳送10個探測報文仍然沒反應,伺服器就認為客戶端出了故障,接著就關閉連線。
本文並非原創內容,僅做了知識整理,便於自己理解與記憶
參考連線
清晰)
SOCKET 通訊原理
源 基於tcp ip協議的網路程式設計 定義變數 獲得winsock版本 載入winsock庫 初始化 建立套接字 設定套接字選項 關閉套接字 解除安裝winsock庫 釋放所有資源 整個程式架構分為兩大部分,伺服器端客戶端。伺服器socket程式流程 socket bind listen acce...
Socket 通訊原理
socket,又稱 套接字 網路上的兩個程式通過乙個雙向的通訊連線實現資料的交換,這個連線的一端稱為乙個 socket。socket 的英文願意是 孔 或 插座 在 internet 上的主機一般執行了多個服務軟體,同時提供幾種服務。每種服務都開啟乙個 socket,並繫結到乙個埠上,不同的埠對應不...
Socket 通訊原理
socket 的中文翻譯過來就是 套接字 套接字是什麼,我們先來看看它的英文含義 插座。socket 就像乙個 插座,負責連通兩端的 進行點對點通訊,讓 可以進行通訊,埠就像插座上的孔,埠不能同時被其他程序占用。而我們建立連線就像把插頭插在這個插座上,建立乙個 socket 例項開始監聽後,這個 插...