【Linux】UDP與TCP協議

目錄

UDP協議

1.1通信流程

1.2函數?

socket

bind

?sendto

recvfrom

close?

1.3實現udp通信

TCP協議

1.1TCP頭部結構

1.2通信流程

三次握手

正式通信

四次揮手

1.3協議特性

面向字節流

可靠傳輸

序列號和確認號

重傳機制

流量控制和擁塞控制

1.4常用函數

socket

bind

listen

accept

connect

send

recv

close?

1.5實現tcp通信


socket又稱套接字,他的存在是為了解決:

  1. 不同協議的識別TCP?UDP
  2. 不同主機的識別(哪個IP發 哪個IP收)
  3. 不同進程的識別(哪個端口發 哪個端口收)?

UDP協議

????????UDP(user datagram protocol)的中文叫用戶數據協議報,屬于傳輸層。UDP是面向非連接的協議,它不與對方建立連接,而是直接把我要發的數據報發給對方。所以UDP適用于一次傳輸數據量很少、對可靠性要求不高的或對實時性要求高的應用場景。

1.1通信流程

udp通信直接傳輸數據,不關心數據是否丟包不會進行重傳。

1.2函數?

socket

#include <sys/socket.h>

int socket(int family,int type,int protocol);

  • 功能:創建一個用于網絡通信的socket套接字
  • family:協議族(AF_INET(IPv4)、AF_INET6(IPv6)、PF_PACKET(鏈路層編程))
  • type:套接字類(SOCK_STREAM(流式套接字)、SOCK_DGRAM(數據報式套接字)SOCK_RAW(原始套接字))
  • protocol:協議類別(0、IPPROTO_TCP、IPPROTO_UDP)一般置0
  • 返回值:套接字

bind

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  • 功能:將socket與本機上的一個端口綁定,隨后就可以在該端口監聽服務請求
  • sockfd:正在監聽端口的套接口文件描述符,通過socket獲得
  • addr:需要綁定的IP和端口
  • addrlen:addr的結構體的大小
  • 返回值:失敗返回一個小于0的值,成功返回大于等于0的值

一般只有服務器端才需要“顯示”綁定端口;client的端口號一般由client的OS隨機選擇,client不需要“顯示”地綁定IP和端口號,當client第一次給服務器發消息時OS會自動綁定IP和端口號。

struct sockaddr
{sa_family_t sa_family; // 2字節char sa_data[14] //14字節
};
  • struct sockaddr_in:IPv4地址結構
  • struct sockaddr:通用地址結構
_sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);//填服務器端的信息
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(_localport);
local.sin_addr.s_addr = INADDR_ANY;//將套接字與服務器端信息綁定
int n = ::bind(_sockfd, (struct sockaddr *)&local, sizeof(local));

?sendto

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
? ? ? ? ? ? ? const struct sockaddr *dest_addr, socklen_t addrlen);
  • 功能:發送數據、
  • sockfd:正在監聽端口的套接字文件描述符,通過socket獲得。
  • buf:發送緩沖區,往往是使用者定義的數組,該數組裝有要發送的數據
  • len:發送緩沖區的大小,單位是字節
  • flags:填0即可
  • dest_addr:指向接收數據的主機地址信息的結構體,也就是該參數指定數據要發送到哪個主機哪個進程
  • addrlen:表示第五個參數所指向內容的長度
  • 返回值:成功返回發送數據長度,失敗返回-1。

recvfrom

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
? ? ? ? ? ? ? ? struct sockaddr *src_addr, socklen_t *addrlen);

  • sockfd:正在監聽端口的套接口文件描述符,通過socket獲得
  • buf:接收緩沖區,往往是使用者定義的數組,該數組裝有接收到的數據
  • len:接收緩沖區的大小,單位是字節
  • flags:一般置0
  • src_addr:指向發送數據的主機地址信息的結構體,也就是我們可以從該參數獲取到數據是誰發出的
  • addrlen:表示第五個參數所指向內容的長度
  • 返回值:成功返回接收成功的數據長度,失敗返回-1

close?

#include <unistd.h>
int close(int fd);

  • 功能:關閉某個文件描述符
  • fd:socket產生的fd(返回值)

1.3實現udp通信

udp通信的簡單實現:Linux/udp_echo_server · swi/c++ - 碼云 - 開源中國

TCP協議

????????TCP是面向連接的協議,這是因為在一個應用進程可以開始向另一個應用進程發送數據之前,這兩個進程必須先相互“握手”,即它們必須相互發送某些預備報文段,以建立確保數據傳輸的參數。它有以下幾個特點:

  1. 面向連接:TCP一定是“一對一”的,無法像 UDP 協議那樣在同一時刻像多個主機發送消息,即無法做到一對多;
  2. 可靠的:無論的網絡鏈路中出現了怎樣的鏈路變化,TCP 都可以保證一個報文一定能夠到達接收端(當然不是說絕對可靠);
  3. 基于字節流:消息是“沒有邊界”的,所以無論我們消息有多大都可以進行傳輸。并且消息是“有序的”,當前一個消息沒有收到的時候,即使它先收到了后面的字節已經收到,那么也不能扔給應用層去處理,同時對重復的報文會自動丟棄。

1.1TCP頭部結構

?

  • 序列號:在連接建立時由計算機計算出的初始值,通過 SYN 包傳給對端主機,每發送一次新的數據包,就累加一次該序列號的大小。用來解決網絡包亂序問題
  • 確認應答號:指下次期望收到的數據的序列號,發送端收到這個確認應答以后可以確認確認應答號減一的數據包已經被正常接收。主要用來解決不丟包的問
  • ACK:用以指示確認字段中的值是有效的,即該報文段包括一個對已被成功接收的報文段的確認
  • RST:用以指示連接的強制拆除,當接收到錯誤連接時會發送RST位置為1的報文
  • SYN:用以指示連接的建立,該位為1的報文表示希望建立連接
  • FIN:用以指示連接的終止,該位為1的報文表示希望斷開連接

1.2通信流程

三次握手

正式通信

?建立連接過程:

????????服務端創建完監聽套接字使用accept等待用戶連接,當用戶連接時監聽套接字會起到"接客"的作用,此時再創建一個新的套接字來進行服務,而監聽套接字繼續等待新的用戶。用于服務的套接字由accept函數返回。

四次揮手

????????最開始的時候,客戶端和服務器都是處于ESTABLISHED狀態,然后客戶端主動關閉,服務器被動關閉。

  • 第一次揮手 客戶端發出連接釋放報文,并且停止發送數據。此時客戶端進入FIN-WAIT-1(終止等待1)狀態。
  • 第二次揮手 服務器端接收到連接釋放報文后,發出確認報文(應答)。此時服務端就進入了CLOSE-WAIT 關閉等待狀態。
  • 第三次揮手 客戶端接收到服務器端的確認請求后,客戶端就會進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文,服務器將數據發送完畢后,就向客戶端發送連接釋放報文,服務器就進入了LAST-ACK(最后確認)狀態,等待客戶端的確認。
  • 第四次揮手 客戶端收到服務器的連接釋放報文后,發出應答此時,此時客戶端就進入了TIME-WAIT(時間等待)狀態,但此時TCP連接還未終止,必須要經過2MSL后(等待最長報文壽命時間,確保發送的應答被服務端收到),當客戶端撤銷相應的TCB后,客戶端才會進入CLOSED關閉狀態,服務器端接收到確認報文后,會立即進入CLOSED關閉狀態,到這里TCP連接就斷開了,四次揮手完成。

1.3協議特性

面向字節流

TCP以字節流的方式傳輸數據,沒有消息邊界,需要應用層進行數據的分包和組包12。這種方式使得TCP能夠靈活地處理各種長度的數據,但也可能導致黏包問題。黏包問題可以通過以下方法解決:

  1. 數據定長:規定數據的長度。

  2. 特殊字符進行間隔:使用特殊字符分隔數據。

  3. 在不定長數據的應用層頭部中添加數據長度字段:接收方根據頭部長度,接收該長度的數據。

可靠傳輸

TCP提供可靠的數據傳輸服務,能夠在數據傳輸過程中檢測和糾正錯誤,確保數據的完整性、順序性和可靠性。TCP通過以下機制確保數據的可靠傳輸:

  • 序列號和確認號:每個數據包都有一個序列號,接收方通過確認號告知發送方哪些數據已成功接收。

  • 重傳機制:如果發送方未收到確認,會重新發送數據包。

  • 流量控制:通過滑動窗口機制,動態調整發送速率,避免接收方緩沖區溢出。

  • 擁塞控制:通過慢啟動、擁塞避免等算法,動態調整發送速率,避免網絡擁塞。

序列號和確認號

序列號(seq)

????????序列號的主要作用是跟蹤每個數據包中的數據在整個數據流中的位置。當TCP連接建立時,每一端都會隨機選擇一個初始序列號(ISN),之后傳輸的數據包的序列號將基于這個初始值遞增。例如,如果一個數據包的序列號是100,且包含100字節的數據,那么下一個數據包的序列號將從200開始。這樣,即使數據包在傳輸過程中到達順序被打亂,接收端也能根據序列號重新組裝數據,確保數據的順序性和完整性。

確認號(ack)

????????確認號則是接收端用來告訴發送端哪些數據已經被成功接收的。當接收端收到數據后,它會發送一個確認包,其中包含的確認號是接收到的數據的序列號加1。發送端通過檢查這個確認號來確定數據是否需要重傳。例如,如果發送端收到的確認號是101,那么它知道序列號為100的數據包已被接收端成功接收。

?應答的情況有以下兩種:

?

重傳機制

超時重傳

????????當TCP發送一個數據包后,它會啟動一個定時器等待接收方的確認應答(ACK)。如果在定時器到期之前沒有收到ACK,TCP會認為數據包可能已丟失,并重新發送該數據包。這個過程稱為超時重傳。超時重傳時間(RTO)的設置非常重要,它應該略大于數據包往返時間(RTT)。

快速重傳

????????快速重傳是另一種重傳機制,它不依賴于定時器,而是基于接收到的重復ACK信號。如果發送方連續收到三個相同的ACK,它會立即重傳那些被認為丟失的數據包,而不需要等待定時器超時。

超時重傳:

(數據丟包)

(應答丟包)?

?為什么要等待一個特定時間?
? ? ? ? 如果該等待時間過長會導致網絡空隙時間增大,降低網絡傳輸效率。如果等待時間過短,可能會在應答未到來時進行重傳,導致網絡負荷增大。

?快速重傳:

流量控制和擁塞控制

流量控制:

作用:為了解決發送方和接收方發送和接收能力不匹配而導致的數據丟失問題,當發送方發送的太快,接收方來不及接受就會導致數據丟失;

方式:由接收端采用滑動窗口的形式,告知發送方允許/停止發包解決TCP丟包問題。

擁塞控制:

作用:為了解決過多的數據注入到網絡導致網絡崩潰和超負荷問題;

方式:由發送方采用擁塞窗口的形式去判斷網絡狀態,從而采取不同算法執行TCP動態發包解決網絡整體質量問題。

慢啟動算法:
????????發送方先探測網絡擁塞程度,并不是一開始就發送大量的數據,發送方會根據擁塞程度增大擁塞窗口。(例如:發2個數據段得到應答,再去嘗試發4個數據段...直到找到合適數量的數據段)

1.4常用函數

socket

#include <sys/socket.h>

int socket(int family,int type,int protocol);

  • 功能:創建一個用于網絡通信的socket套接字
  • family:協議族(AF_INET(IPv4)、AF_INET6(IPv6)、PF_PACKET(鏈路層編程))
  • type:套接字類(SOCK_STREAM(流式套接字)、SOCK_DGRAM(數據報式套接字)SOCK_RAW(原始套接字))
  • protocol:協議類別(0、IPPROTO_TCP、IPPROTO_UDP)一般置0
  • 返回值:套接字

bind

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  • 功能:將socket與本機上的一個端口綁定,隨后就可以在該端口監聽服務請求
  • sockfd:正在監聽端口的套接口文件描述符,通過socket獲得
  • addr:需要綁定的IP和端口
  • addrlen:addr的結構體的大小
  • 返回值:失敗返回一個小于0的值,成功返回大于等于0的值

listen

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd,int backlog)

  • 功能:listen函數使socket處于被動的監聽模式,并為該socket建立一個輸入數據隊列,將到達的服務請求保存在此隊列中,直到程序處理它們。
  • sockfd:傳入bind的sockfd。
  • backlog:請求連接隊列的最大長度,這個隊列指的是多個客戶端都請求建立連接時,會把這些連接暫時存入隊列中,以便下一步調用accept接受連接。
  • 返回值:成功則返回0,否則-1。

accept

#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr* addr, socklen_t addrlen);

  • 功能:讓服務器接受客戶的連接請求。
  • sockfd:經過bind和listen的sockfd。
  • addr:此處addr參數是傳出的,函數成功執行后,存的是客戶端的IP和端口。
  • addrlen:addr的結構體的大小
  • 返回值:如果成功,則會返回一個非負整數,也就是accepted socket的文件描述符,后續的通信則用這個文件描述符,如果失敗則返回-1。

connect

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr* addr, socklen_t addrlen);

  • 功能:讓服務器接受客戶的連接請求。
  • sockfd:由socket函數創建的文件描述符。
  • addr:保存服務端的IP和端口
  • addrlen:addr的結構體的大小
  • 返回值:0表示成功,-1表示錯誤失敗。

send

#include <sys/types.h> ?

?#include <sys/socket.h>

int send(?SOCKET?s,????const char FAR *buf,????int len,????int flags );??

  • 功能:數據發送函數。
  • s:指定發送端套接字描述符。
  • buf:指明一個存放應用程序要發送數據的緩沖區。
  • len:要發送的數據的字節數。
  • flags:一般置0。
  • 返回值:n(n大于0意為成功發送 n 個字節;n等于0意為對端關閉連接;n小于0意為出錯或者被信號中斷或者對端 TCP 窗口太小數據發不出去(send)或者當前網卡緩沖區已無數據可收(recv))

recv

#include <sys/types.h> ?

?#include <sys/socket.h>

int recv(int s, void *buf, int len, unsigned int flags);

  • 功能:數據接收函數。
  • s:指定接收端套接字描述符
  • buf:指向一個緩沖區,用于存放接收到的數據。
  • len:緩沖區的長度。
  • flags:一般置0。
  • 返回值:n(n大于0意為成功接收?n 個字節;n等于0意為對端關閉連接;n小于0意為出錯)

close?

#include <unistd.h>
int close(int fd);

  • 功能:關閉某個文件描述符
  • fd:socket產生的fd(返回值)

1.5實現tcp通信

tcp通信的簡單實現:Linux/tcp_echo_server · swi/c++ - 碼云 - 開源中國

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87203.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87203.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87203.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gbase8s之MyBatis批量update問題

源代碼 <update id"updateDynamicTableData"><foreach collection"mapList" item"map" separator";">UPDATE ${tableName} SET<foreach collection"map" item"value" index"key" separ…

博圖SCL中WHILE語句的使用詳解及案例

在西門子TIA Portal的SCL&#xff08;結構化控制語言&#xff09;編程中&#xff0c;WHILE循環是處理條件迭代任務的核心工具。它根據布爾表達式動態控制循環執行&#xff0c;適用于不確定循環次數的場景。下面從語法、執行流程、注意事項到實際案例全面解析。 一、WHILE循環基…

簡單聊聊JVM中的幾種垃圾收集算法

3.4、分代收集算法 分代收集算法&#xff0c;可以看成以上內容的延伸。它的實現思路是根據對象的生命周期的不同&#xff0c;將內存劃分為幾塊&#xff0c;比如把堆空間劃分為新生代和老年代&#xff0c;然后根據各塊的特點采用最適當的收集算法。 在新生代中&#xff0c;存在…

依賴已導入,已下載,無法使用問題

明明已經導入依賴&#xff0c;卻無法使用相關注解 于是&#xff0c;我使用 mvn dependency:tree -Dverbose 來查看是否有依賴沖突 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal on project agileboot…

答題考試系統小程序ThinkPHP+UniApp

ThinkPHPUniapp開發的小程序答題考試系統&#xff0c;支持多種試題類型、多種試題難度、練題、考試、補考模式&#xff0c;提供全部前后臺無加密源代碼&#xff0c;支持私有化部署. 更新日志 V1.7.1修復一些問題 解決考場成績列表重復問題&#xff1b; 解決后臺材料題選擇子…

DHCP服務管理

目錄 DHCP協議 DHCP的優勢 DHCP的分配方式 應用場景 注意 工作流程 何時更新租約 當客戶端重啟后 客戶端類型 DCHP安裝與配置 網絡規劃&#xff1a; 配置 DHCP 作用域 啟動 DHCP 服務 配置路由器 配置路由器網卡 IP 開啟 IP 轉發&#xff08;確保跨網段通信&…

12.UDP客戶端

準備工作 硬件準備&#xff1a;確保你的STM32板子已經正確連接了DP83848網絡芯片。 軟件設置&#xff1a; 安裝好STM32CubeMX用于配置工程。 選擇合適的STM32 HAL庫版本。 如果可能的話&#xff0c;安裝LwIP庫支持TCP/IP協議棧。 步驟 1. 使用STM32CubeMX配置項目 打開…

希爾腳本簡介及常用命令代碼整理

一、Shell 腳本簡介 1. 定義 Shell 是用戶與操作系統內核交互的橋梁&#xff0c;常見類型有 Bash、Zsh、PowerShell 等。Shell 腳本則是一系列 Shell 命令的集合&#xff0c;通常保存為后綴為.sh 的文本文件。 2. 作用 類別描述自動化重復性任務例如定期備份數據、執行定時…

【人工智能下的智算網絡】廣域網優化

一、廣域網絡多路徑I/O寫的并行路徑優化方案 1.1、數學建模 網絡拓撲優化? 1. ?拓撲抽象與路徑發現? ?鄰接矩陣建模?&#xff1a; 將網絡節點抽象為圖頂點 G (V, E)&#xff0c;鏈路帶寬與延遲定義為邊權 w(e)。構造鄰接矩陣 A&#xff0c;其中元素 A_{ij} 表示節點 …

AI測試開發工程師如何用大模型調用工具:從入門到實踐

在軟件測試領域&#xff0c;測試工程師常常面臨測試用例設計復雜、數據生成繁瑣、結果驗證耗時等挑戰。隨著大語言模型&#xff08;LLM&#xff09;的迅速發展&#xff0c;Chat類大模型&#xff08;如GPT、LangChain支持的模型&#xff09;為測試開發提供了一種全新思路——工具…

遷移學習基礎

知識的“跨界復用” 你是一位經驗豐富的廚師&#xff08;源模型&#xff09;&#xff0c;尤其擅長做意大利菜&#xff08;源任務/源域&#xff09;。現在&#xff0c;老板讓你去新開的一家融合餐廳工作&#xff0c;需要你做亞洲菜&#xff08;目標任務/目標域&#xff09;。你…

AI醫生24小時在線:你的健康新‘算法監護人

2025年仲夏&#xff0c;中國醫療AI領域迎來爆發式突破&#xff1a;羅湖醫院集團率先部署"DeepSeek-騰訊混元"雙AI診療系統&#xff0c;實現患者15分鐘極速就診閉環&#xff1b;復旦大學研發的微量血液檢測技術取得重大突破&#xff0c;僅需數滴血樣即可篩查上千種疾病…

Java 中 DataSource-數據源 的基礎介紹

Java 中 DataSource-數據源 的基礎介紹 一、核心概念解析1.1 數據源&#xff08;Data Source&#xff09;1.2 數據庫連接池&#xff08;Connection Pool&#xff09;1.3 二者關系1.4 DataSource 接口 二、DataSource 解決的問題與優勢2.1 DataSource 的作用2.2 傳統方式的局限性…

Vue + Vite 項目部署 Docker 全攻略:原理、路由機制、問題排查與開發代理解析

Vue Vite 項目部署 Docker 全攻略&#xff1a;原理、路由機制、問題排查與開發代理解析 本文面向希望將 Vue 3 Vite 項目部署到生產環境&#xff08;Docker NGINX&#xff09;并深入理解路由行為、構建機制與常見問題排查的開發者。 &#x1f4e6; 一、項目準備 以 Vue 3 …

Vue3 + TypeScript 使用 v-bind() 在 <style scoped> 中動態設置 CSS 樣式值

使用要求&#xff1a; Vue 3.3 <style scoped>&#xff0c;Vue 的 v-bind() 在 CSS 中只支持在 scoped style 或 CSS Modules 中使用v-bind("cssVar") 雙引號包裹響應式變量&#xff0c;變量 cssVar 必須是 Vue 的響應式數據&#xff08;如 ref 或 reactive&…

php列表頭部增加批量操作按鈕,多選訂單數據批量微信退款(含微信支付SDK)

index_search.html data-table-id:表格id data-rule:需要傳輸的列表字段 data-action:控制器方法 <a class="layui-btn layui-btn-primary layui-btn-sm" style=

小程序還沒有上線就提示小程序違規,支付失敗

如果出現這種情況&#xff0c;一般情況下不是真正的違規&#xff0c;是因為在小程序后臺&#xff0c;沒有設置訂單詳情頁面的path地址的原因 1.首先看一下&#xff0c;在站內信中是否有相關訂單的通知&#xff1a;站內信&#xff08;小程序通知中心&#xff09;查看是否看到 關…

展開說說Android之Glide詳解_源碼解析

基于上一篇介紹了Glide的使用篇本文分析一下Glide的源碼實現&#xff0c;看看我們簡單幾步就實現的圖片展示功能在源碼中是怎樣完成的。 一、Glide中的核心文件 先逐個介紹一下個人以為的幾個核心類&#xff1a;? 1、Glide Glide是必經的入口&#xff0c;通過Glide.get(con…

商品中心—6.商品考核系統的技術文檔二

大綱 1.基于大數據系統的商品考核數據指標 2.基于商品考核數據指標的商品考核流程 3.商品考核失敗后的處理 考核流程的設計 4.商品考核系統數據庫模型設計 5.商品考核系統核心接口 6.商品生命周期系統的定時考核任務 6.商品生命周期系統的定時考核任務 (1)定時任務處理…

鴻蒙組件通用事件開發全攻略:從基礎交互到工程實踐

一、引言&#xff1a;事件系統 —— 構建交互體驗的核心樞紐 在鴻蒙應用開發體系中&#xff0c;組件事件系統是連接用戶操作與應用邏輯的關鍵橋梁。從基礎的點擊交互到復雜的多觸點手勢&#xff0c;通用事件覆蓋了全場景設備的交互需求。本文將系統解構鴻蒙事件體系的核心機制…