日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

1. 應用層

1.1 server

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

1.2 client

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

1.3 三次握手建立連接

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

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

(3) 客戶端再次收到服務器發送來的 TCP 段后,檢查到帶有 SYN 和 ACK 標志,于是客戶端一方連接已經建立成功,此時 connect 函數返回??蛻舳藙摻ㄒ粋€ TCP 段,將 ACK 標志置位,同時將 ack 的值設置為 4269858,發送給服務器。

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

2. kernel流程

2.1?client 通過connect()發送SYN報文,向服務器發起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

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

2.2?tcp_rcv_state_process(三次握手狀態機)

網卡驅動 --> netif_receive_skb - --> ip_rcv ---> ip_local_deliver_finish ---> tcp_v4_rcv -> tcp_v4_do_rcv -> tcp_rcv_state_process

1) client

客戶端收到SYN+ACK報文,然后回ACK報文

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報文, 發送SYN+ACK報文

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變為TCP_NEW_SYN_RECV

b. 收到客戶端ACK報文

連接已經建立,喚醒阻塞的accept函數。

首先在tcp_v4_rcv中,建一個新的sock進入TCP_SYN_RECV狀態;

然后調用tcp_child_process ->?tcp_rcv_state_process,最終進入TCP_ESTABLISHED狀態,并放入accept隊列通知select/epoll。

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

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

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

2.4 accept

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

2.5 bind

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。