TCP網絡編程中connect() 、listen() 和accept()三者之間關系


TCP網絡編程開發分為服務器端和客戶端兩個部分 

對於服務器端開發主要流程--類似於 接電話過程

socket()[找到一個可以通話的手機]----->bind()[插入一個固定號碼]------>listen()-------> accept------->recv()------->send()------>close();

對於客戶端開發主要流程----類似於打電話過程

socket()----->connect()------>recv/read/send------>close()

對於TCP協議 =建立連接就在客戶端connect()與服務器listen之間 建立TCP連接(三次握手) 

對於四次揮手 狀態兩個PC之間close狀態

 

1.  Connect()函數:是一個阻塞函數 通過TCp三次握手父服務器建立連接

客戶端主動連接服務器 建立連接方式通過TCP三次握手通知Linux內核自動完成TCP 三次握手連接 如果連接成功為0 失敗返回值-1

一般的情況下 客戶端的connect函數 默認是阻塞行為 直到三次握手階段成功為止。

 

2.服務器端的listen() 函數:不是一個阻塞函數: 功能:將套接字 和 套接字對應隊列的長度告訴Linux內核

  他是被動連接的 一直監聽來自不同客戶端的請求 listen函數只要 作用將socketfd 變成被動的連接監聽socket 其中參數backlog作用 設置內核中隊列的長度 。

 

3.accept() 函數 阻塞:從處於established 狀態的隊列中取出完成的連接 當隊列中沒有完成連接時候 會形成阻塞,直到取出隊列中已完成連接的用戶連接為止。

  問題一:服務器沒有及時調用accept函數取走完成連接的隊列怎么辦?

服務器的連接隊列滿掉后,服務器不會對再對建立新連接的syn進行應答,所以客戶端的 connect 就會返回 ETIMEDOUT。但實際上Linux的並不是這樣的 當TCP連接隊列滿了之后 Linux並不會書中所說的拒絕連接,只是會延時連接。

 

2.TCP三次握手機制:三次握手機制保證通信是雙工,可靠保證 更多通過重傳機制

1.Client 主動向處於listen狀態的服務器發送 SYN_SENT 報文;

2. Server SYN_RECVD之后 分配資源內存同時向client發送 SYN_ACK 確認接受的報文

3.Client 接受到服務器SYN_ACK 本地開辟內存資源 同時回復Server 發送SYN_ACK+I報文已經接受ACK報文信息 至此TCP連接建立起來

 

3.TCP 四次揮手:

  1.客戶端A向服務器發送FIN,用來用來關閉A到serverB的數據傳送

  2.服務器B接受到 這個FIN 它發回一個ACK確認報文 確認序列號+1 (客戶端處於FIN_WAIT2)

  3.服務器B關閉客戶端A的連接發送一個FIN報文 自己進行連接關閉

  4.客戶端A 接受到server的FIN報文 回復ACK報文確認 此時客戶端進入TIME_WAT d等待 經過2MLS 沒有收到服務器的ACK確認信息自動進行關閉。

FIN報文 告訴自己 對方沒有數據進行發送 並不能阻止自己發送數據,因此有可能還是有些數據發生給對方因此在關閉連接時候 ACK報文與FIN報文是分開 這也導致關閉時候需要四次揮手

 

問題一:TIME_WAT 狀態中還需要等待2MS時間后才進行關閉

  雖然雙方都同意關閉連接 按理可以直接回到 CLOSED 狀態,事實上網絡不可靠的 無法保證服務器能夠接受到客戶端的ACK確認消息。有可能讓處於last_ACK 的server 認為超時重復FIN報文,所以TIME_WAT狀態 作用重發可能丟失的ACK報文


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM