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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux网络编程-----TCP连接及相关问题

發布時間:2024/4/19 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux网络编程-----TCP连接及相关问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

c/s模型在建立連接時的流程如下

//服務器端 int sockfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(8080); servaddr.sin_addr.s_addr = INADDR_ANY;bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); listen(sockfd, 10);struct sockaddr_in addr; socklen_t len = sizeof(addr); int fd = accept(sockfd, (struct sockaddr*)&addr, &len);/* ... */close(fd); close(sockfd); //客戶端 int sockfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(8080); inet_aton("127.0.0.1", &servaddr.sin_addr);connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr);/* ... */close(sockfd);

在客戶端connect,服務器accept以及二者的close過程中,代表著TCP連接的建立和終止,也就是常說的TCP三路握手和四路揮手

三路握手

建立一個TCP連接時會發生如下情形

  • 服務器端必須準備好接受客戶端的連接請求,通常是通過調用socket,bind,listen這三個函數來完成的,稱之為被動打開
  • 客戶端通過調用connect發起主動打開,主動連接到服務器端,這個過程中客戶端發送一個SYN(同步)分節到服務器端,它告訴服務器將在連接中發送的數據的初始序列號(可以理解為數據的起始號碼,只有號碼在這個序列號之后的數據才會被認為是當前客戶端發送的數據),此時客戶端狀態為SYN_SENT
  • 服務器必須確認(ACK)客戶的SYN,將客戶端的初始序列號記錄下來。同時自己也需要發送一個SYN分節,它告訴客戶端在連接中發送的數據的初始序列號(只有號碼在這個序列號之后的數據才會被認為是當前服務器端發送的數據)。服務器端在一個分節中同時發送SYN和ACK。此時服務器端狀態為SYN_RCVD
  • 客戶端必須確認服務器端的SYN,將服務器端的初始序列號記錄下來,發送確認ACK到服務器端,同時connect函數返回,客戶端狀態變為ESTABLISHED
  • 服務器端接受到來自客戶端的確認(ACK),accept函數返回,服務器端狀態變為ESTABLISHED,建立TCP連接
  • 至此完成TCP的三路握手

    四路揮手

    TCP建立連接需要3個分節,而終止連接卻需要4個分節
    以下以客戶端先調用close為例
    1. 客戶端首先調用close函數關閉套接字,執行為主動關閉,該端的TCP發送一個FIN分節到服務器端,表示數據發送完畢,客戶端進入FIN_WAIT_1狀態
    2. 接收到這個FIN的服務器端執行被動關閉。這個FIN由該端的TCP確認,發送確認分節(ACK)到客戶端,FIN的接受也作為一個文件結束符傳遞給服務器端應用進程,也就是說如果服務器端進程調用recv/read函數,會讀到相當于文件結束符的FIN,從而表示客戶端已經發送完數據,執行了close。至此服務器端進入CLOSE_WAIT狀態,意思是等待調用close
    3. 客戶端接收到來自服務器端的確認分節(ACK),進入FIN_WAIT_2狀態
    4. 一段時間之后(通常是recv/read到FIN后),服務器端執行close函數關閉套接字,這導致服務器端TCP也發送一個FIN到客戶端,此時服務器端進入LAST_ACK狀態
    5. 客戶端接收到服務器端發送的FIN并確認這個FIN,同時發送確認(ACK)到服務器端,同時進入TIME_WAIT狀態
    6. 服務器端接受到來自客戶端的確認(ACK),進入CLOSED狀態,至此TCP連接終止

    相關問題

    為什么是三路握手,不是二路或者四路?

  • 因為TCP連接具有高效,穩定等特性,而三路握手正好可以滿足TCP的這種特性。
  • 如果是四路握手,即服務器端的SYN和ACK會分開發送。也就是客戶端發送SYN到服務器端,服務器端記錄客戶端的數據的初始序列號,發送確認分節ACK給客戶端,然后發送自己的數據初始序列號SYN到客戶端。顯然這兩步可以合并在一個分節中發送,實現高效性
  • 如果是二路握手,即客戶端收到服務器端的SYN和ACK后不發送確認(ACK)到服務器端,這就會出現如下問題:客戶端知道服務器端能夠收到自己的數據,而服務器端不知道客戶端能不能收到自己的數據,無法實現穩定性
  • 綜上,TCP的連接采用三路握手

  • 服務器端accept返回的套接字占用的端口和監聽套接字監聽的端口是否相同?
    相同,服務器端已建立的TCP連接套接字使用和監聽套接字相同的端口。
    直觀的考慮,http服務器監聽80端口的連接,服務器不可能給成千上萬個訪問分配不同的端口,所以通過accept返回的套接字使用的也是監聽套接字的端口。
    套接字由<源ip,源端口,目的ip,目的端口,協議>這個五元組唯一確定的,所以僅僅端口相同不能說明TCP連接是相同的


    套接字的結構是什么樣的,為什么send時只傳入一個套接字就知道往什么地址端口發送數據?
    套接字表面上使用int類型,其實內部由<源ip,源端口,目的ip,目的端口,協議>這個五元組唯一確定,
    在connect返回時,內核將套接字的五元組進行賦值,記錄目的ip和目的端口,所以在之后的recv/send等io操作時只需要傳入一個套接字遍知道究竟從什么地址,端口接受數據,往什么地址,端口發送數據了。
    accept同理


    客戶端套接字的端口是如何確定的,為什么沒有手動綁定(使用bind函數)?
    在tcp連接中,客戶端套接字的端口是由內核隨機分配的,因為客戶端不是客戶端,需要知道具體端口供其他進程連接,所以也沒必要使用bind綁定地址和端口,只需要手動connect到服務器的地址和端口即可


    如何理解主動關閉的一方會進入TIME_WAIT狀態?
    在TCP連接終止時,主動關閉(首先調用close)的一方會進入這個狀態,這個狀態的持續時間是最長分節生命期的兩倍,有時候稱之為2MSL,有些實現是30s,有些則是2分鐘不等。
    TIME_WAIT狀態有兩個存在的理由

  • 可靠地實現TCP全雙工連接的終止
  • 允許老的重復分節在網絡中消逝
  • 第一個理由可以假設四路揮手的最后一個確認分節(ACK)丟失,服務器端(仍然假設客戶端主動關閉連接)在發送FIN一段時間后仍然沒有收到來自客戶端的確認(ACK),這就導致了服務器端認為客戶端沒有接受到自己的FIN分節,從而重新發送FIN分節到客戶端。
    因為客戶端此時處于TIME_WAIT狀態,仍然保留著TCP連接時的雙方信息,所以收到FIN后也重新發送確認(ACK)到服務器端,從而確保服務器端可以收到ACK正常關閉。
    如果客戶端不進入TIME_WAIT狀態而直接關閉,那么當最后的ACK分節丟失,服務器端重新發送FIN給客戶端后,客戶端已經沒有了雙方連接的信息,也就是說不能識別來自服務器端的這個FIN,就會發送一個RST(另一種類型的TCP分節),服務器端便認為TCP連接出現了錯誤
    第二個理由可以假設在客戶端12.106.32.254的1500端口和服務器端206.168.112.219的21端口之間有一個TCP連接被建立,客戶端執行主動關閉,而后客戶端又重新發起連接
    如果客戶端關閉后不進入TIME_WAIT狀態,那么客戶端內核會分配第一個可用的端口即1500(因為剛關閉,所以可用),這就導致了兩次的TCP連接的客戶端地址和端口是一樣的,如果此時發送一段數據給服務器,服務器會誤認為這個數據是第一次的連接還沒有接受完的數據,也就是說會把本次連接誤認為是剛開始的連接
    如果客戶端關閉后進入TIME_WAIT狀態,那么內核不會分配一個處于TIME_WAIT狀態的(ip,端口)給進程使用,就解決了上述的問題,又因為2msl足以讓先前的數據報文消逝,所以2msl足矣


    服務器端accept完客戶端請求后可不可以關閉監聽套接字?
    可以,程序可以在任何時候關閉監聽套接字,只是在關閉之后不能夠再使用accept接受客戶端請求。關閉監聽套接字后不妨礙已經建立的tcp連接。另外,四路揮手是對于tcp連接而言的,對監聽套接字使用close會立即關閉它,不需要四路揮手。


    傳統iso協議和tcp/ip協議的具體內容?
    iso七層模型由應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層,物理層構成
    tcp/ip四層模型由應用層,傳輸層,網絡層,數據鏈路層構成

    • 應用層:各種應用程序協議,HTTP,FTP,TALENT等
    • 傳輸層:TCP數據流傳輸,面向連接的穩定,高效,可靠的傳輸協議,支持重傳。UDP數據報傳輸,面向無連接的傳輸協議,速度快,但是不可靠,適用于實時通信
    • 網絡層:ip協議
    • 數據鏈路層:負責數據傳輸

    socket是什么,怎么理解socket的應用?
    tcp/ip協議中用戶程序直接接觸的是應用層,而對于底層的tcp協議棧,需要有一種接口供應用程序調用,socket正是這樣一種接口,供用戶程序與tcp協議棧交互,可以理解socket為tcp協議的一種抽象接口

    總結

    以上是生活随笔為你收集整理的linux网络编程-----TCP连接及相关问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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