/* 此處僅設定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的精髓不無裨益,期待著與大家一起進步。
非阻塞connect的實現
需要非阻塞connec的幾種情況 1.三路握手需要時間,這個要視具體的網路情況而定。當然也有可能失敗。在三路握手的時候我們並不需要在原地等待三路握手的完成,可以用這些時間來完成其它事情,然後當這些事情完成後,再去檢測連線是否建立 也就是三路握手是否完成 2.可以用這種技術來同時建立多個連線。web瀏...
非阻塞 connect套接字
非阻塞connect套接字的作用 1 完成乙個connect要花費rtt時間,而rtt波動範圍很大,從區域網上的幾個毫秒甚至是廣域網上的幾秒,這段時間也許有我們要執行的其他處理工作可以執行。2 可以使用這個技術同事建立多個連線。3 許多connect的超時實現以75秒為預設值,如果應用程式想自定義乙...
socket使用非阻塞connect
在使用tcp的connect呼叫時,預設是使用阻塞方式,當伺服器當前不可用時,connect會等待 內部在重試?直到超時時間到達,而這個超時時間是系統核心規定的,不能使用setsocketopt來設定。在碰到伺服器不可用,上層邏輯進行重試時,如果超時時間過長,會產生卡死的感覺,使用者體驗也不佳,所以...