日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux kernel 三次握手建立TCP链接的实现

發(fā)布時間:2023/12/15 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux kernel 三次握手建立TCP链接的实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. 應(yīng)用層

1.1 server

socket() -> bind() -> listen() -> accept() -> recv() & send()

1.2 client

socket() ->? connect() -> send() & recv()

1.3 三次握手建立連接

(1) 客戶端發(fā)送一個 SYN 段(SYN 標(biāo)志位置位),包含初始序號 ISN,在圖中,這個序號的值 seq = 2379453243. 在這個過程中,客戶端是通過 connect 函數(shù)發(fā)起連接請求的,此時 connect 函數(shù)阻塞,等待服務(wù)器發(fā)回 ACK 應(yīng)答。

(2) 服務(wù)器端接收到 SYN 段后(通過listen監(jiān)聽),知道有新的連接請求到來,于是初始化一個序號 ISN,在上面的例子中這個值是 seq = 4269857. 此時服務(wù)器創(chuàng)建一個 TCP 段,將 SYN 和 ACK 標(biāo)志置位,讓 seq = 4269857, ack = 2379453244,然后將這個 TCP 段發(fā)送給客戶端。這個步驟完全有內(nèi)核完成,并將此連接加入未完成連接隊(duì)列。

(3) 客戶端再次收到服務(wù)器發(fā)送來的 TCP 段后,檢查到帶有 SYN 和 ACK 標(biāo)志,于是客戶端一方連接已經(jīng)建立成功,此時 connect 函數(shù)返回。客戶端創(chuàng)建一個 TCP 段,將 ACK 標(biāo)志置位,同時將 ack 的值設(shè)置為 4269858,發(fā)送給服務(wù)器。

(4) 服務(wù)器收到客戶端的 ACK 后,將此連接移到已完成連接隊(duì)列(accept)。

2. kernel流程

2.1?client 通過connect()發(fā)送SYN報(bào)文,向服務(wù)器發(fā)起tcp連接

connect ---->?SYSCALL_DEFINE3(__sys_connect)(socket.c) -> sock->ops->connect ->?inet_stream_connect(af_inet.c) ->?__inet_stream_connect ->?sk->sk_prot->connect ->?tcp_v4_connect(tcp_ipv4.c) ->?tcp_connect(tcp_output.c) ->?tcp_send_syn_data | tcp_transmit_skb(syn)

tcp_connect(): Build a SYN and send it off

對于阻塞調(diào)用,等待后續(xù)握手的完成;對于非阻塞調(diào)用,則直接返回 -EINPROGRESS,然后在select函數(shù)中來捕獲socket的連接、讀寫、異常事件以觸發(fā)相關(guān)操作。

2.2?tcp_rcv_state_process(三次握手狀態(tài)機(jī))

網(wǎng)卡驅(qū)動 --> netif_receive_skb - --> ip_rcv ---> ip_local_deliver_finish ---> tcp_v4_rcv -> tcp_v4_do_rcv -> tcp_rcv_state_process

1) client

客戶端收到SYN+ACK報(bào)文,然后回ACK報(bào)文

case TCP_SYN_SENT: tcp_rcv_synsent_state_process ->?tcp_finish_connect & tcp_send_ack

client tcp state: CLOSING ->? TCP_SYN_SENT ->?TCP_ESTABLISHED

2) server

a. 收到客戶端SYN報(bào)文, 發(fā)送SYN+ACK報(bào)文

case?TCP_LISTEN:?icsk->icsk_af_ops->conn_request ->?tcp_v4_conn_request ->?tcp_conn_request ->?af_ops->send_synack ->?tcp_v4_send_synack

tcp_v4_send_synack():?Send a SYN-ACK after having received a SYN.

server tcp state變?yōu)門CP_NEW_SYN_RECV

b. 收到客戶端ACK報(bào)文

連接已經(jīng)建立,喚醒阻塞的accept函數(shù)。

首先在tcp_v4_rcv中,建一個新的sock進(jìn)入TCP_SYN_RECV狀態(tài);

然后調(diào)用tcp_child_process ->?tcp_rcv_state_process,最終進(jìn)入TCP_ESTABLISHED狀態(tài),并放入accept隊(duì)列通知select/epoll。

server tcp state:? CLOSING ->??TCP_LISTEN ->? TCP_NEW_SYN_RECV ->?TCP_SYN_RECV ->? TCP_ESTABLISHED

2.3? server通過listen操作開始監(jiān)聽,此時就可以接受到client連接請求。

listen ---->?SYSCALL_DEFINE2(listen) ->?__sys_listen ->?sock->ops->listen --->? inet_csk_listen_start

2.4 accept

accept()實(shí)際要做的事件并不多,它的作用是返回一個已經(jīng)建立連接的socket(即經(jīng)過了三次握手),這個過程是異步的,accept()并不親自去處理三次握手過程,而只是監(jiān)聽icsk_accept_queue隊(duì)列,當(dāng)有socket經(jīng)過了三次握手,它就會被加到icsk_accept_queue中,所以accept要做的就是等待隊(duì)列中插入socket,然后被喚醒并返回這個socket。而三次握手的過程完全是協(xié)議棧本身去完成的。換句話說,協(xié)議棧相當(dāng)于寫者,將socket寫入隊(duì)列,accept()相當(dāng)于讀者,將socket從隊(duì)列讀出。這個過程從listen就已開始,所以即使不調(diào)用accept(),客戶仍可以和服務(wù)器建立連接,但由于沒有處理,隊(duì)列很快會被占滿。

2.5 bind

bind操作的主要作用是將創(chuàng)建的socket與給定的地址相綁定,這樣創(chuàng)建的服務(wù)才能公開的讓外部調(diào)用。當(dāng)然對于socket服務(wù)器的創(chuàng)建來說,這一步不是必須的,在listen()時如果沒有綁定地址,系統(tǒng)會選擇一個隨機(jī)可用地址作為服務(wù)器地址。

總結(jié)

以上是生活随笔為你收集整理的linux kernel 三次握手建立TCP链接的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。