以下基於linux核心2.4.0原始碼(**www.yuanma.org/)
/* 此處僅設定socket的狀態為ss_connecting表示連線狀態正在處理;
* 不同之處在於非阻塞情況下,返回值設定為-einprogress表示操作正在處理
* 而阻塞式情況則在獲得ack包後將返回值置為-ealready.
*/err = -einprogress;
break;
}timeo = sock_sndtimeo(sk, flags&o_nonblock); //注意,如果此時設定了非阻塞選項,則timeo返回0
//如果socket對應的sock狀態是syn包已傳送或收到syn包並傳送了ack包,並等待對端傳送第三此的ack包
if ((1...sock->state = ss_connected;
err = 0;
out:
release_sock(sk);
return err;
...上面的描述有乙個問題:對伺服器的響應ack包是什麼時候傳送的?對於非阻塞模式,應該是應用處理過程中
的某個非同步時間;對於阻塞模式,則是在inet_wait_for_connect函式中睡眠時處理。
即網絡卡在收到對方的ack包後,上傳給對應的socket時傳送伺服器的響應ack包
函式呼叫鏈為:netif_rx-->net_rx_action-->...(ip層處理)-->tcp_v4_rcv-->tcp_v4_do_rcv-->
tcp_rcv_state_process-->tcp_rcv_synsent_state_process-->tcp_send_synack-->tcp_transmit_skb...
傳送syn包後,socket對應的sock的狀態變成tcpf_syn_sent,網絡卡收到伺服器的ack傳到tcp層時,根據tcpf_syn_sent
狀態,做相關判斷後再傳送用於第三次握手的ack包。至此,將socket的狀態改為連線建立,即tcp_established。
具體的**大家可以根據我提供的函式呼叫鏈檢視。
注意,以tcpf_字首開頭的狀態都表示是中間狀態,而已tcp_為字首的狀態才是socket的乙個相對穩定的狀態。
這裡有乙個疑問,,根據接收處理原始碼,先前的syn包應該傳送給伺服器的監聽socket,而第三次握手似乎應該傳送給
連線(未真正連線,因為三次握手還沒完成呢)的socket,這個問題有待進一步確認
三、伺服器端支援
伺服器端此時必須是監聽狀態,則其函式呼叫鏈為:
netif_rx-->net_rx_action-->...(ip層處理)-->tcp_v4_rcv-->tcp_v4_do_rcv-->
tcp_rcv_state_process-->tcp_v4_conn_request-->tcp_v4_send_synack...
在tcp_v4_conn_request,中部分**如下:
...case tcp_listen:
if(th->ack) /*監聽時收到的ack包都丟棄?*/
return 1;
if(th->syn) {/*如果是syn包,則呼叫tcp_v4_conn_request*/
if(tp->af_specific->conn_request(sk, skb) < 0)
return 1;
...四、後記
這裡只是給了乙個tcp/ip三次握手原理的實現框架簡述,結合相關理論教材和這個流程,仔細閱讀
linux核心對tcp/ip的實現,對自己理解tcp/ip的精髓不無裨益,期待著與大家一起進步。
tcp三次握手 TCP 三次握手總結
tcp特點概述 tcp segment structure 段結構 step2 server host receives syn,replie with syn ack segment 答覆syn ack報文段 step3 client receives synack,replies with ac...
TCP三次握手與Linux的TCP核心引數優化
tcp是乙個面向連線的協議,在連線雙方傳送資料之前,首先需要建立一條連線。tcp建立連線可以簡單稱為 三次握手 說白了就是建立乙個tcp連線的時候,客戶端和服務端總共要發3個包,socket程式設計裡面執行connect 的時候,將觸發三次握手 斷開tcp連線可以叫做四次握手 socket程式設計裡...
TCP 三次握手
tcp 三次握手 tcp 連線是通過三次握手進行初始化的。三次握手的目的是同步連線雙方的序列號和確認號並交換 tcp 視窗大小資訊。以下步驟概述了通常情況下客戶端計算機聯絡伺服器計算機的過程 1.客戶端向伺服器傳送乙個syn置位的tcp報文,其中包含連線的初始序列號x和乙個視窗大小 表示客戶端上用來...