UDP的socket編程

socket接口

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

參數說明??

參數說明
domain協議族(地址族),如?AF_INET(IPv4)、AF_INET6(IPv6)
type套接字類型,UDP 使用?SOCK_DGRAM(數據報)
protocol通常設為?0(自動選擇),或?IPPROTO_UDP

socket()?的前兩個參數?domain(地址族)和?type(套接字類型)已經分別指定了??網絡層協議??(如 IPv4/IPv6)和??傳輸層協議??(如 TCP/UDP),第三個參數是歷史原因被留了下來,現在一般設為0

底層原理

socket系統調用會創建struct file,struct socket,struct sock等結構體,最終返回該套接字的文件描述符

struct sock?

傳輸層和網絡層的底層實現

struct sock {struct sk_buff_head  sk_receive_queue; // 傳輸層接收緩沖區struct sk_buff_head  sk_write_queue;   // 傳輸層發送緩沖區struct proto       *sk_prot;           // 純粹的傳輸層協議的操作集union {struct inet_sock  inet;            // IPv4的底層結構體struct ipv6_sock  ipv6;            // IPv6的底層結構體};// ...(定時器、擁塞控制、狀態等)
};


struct socket

對struct sock進行封裝,主要是封裝出了用戶級的系統調用操作集

struct socket {struct sock     *sk;       const struct proto_ops *ops; //協議相關的系統調用??(如?bind、connect、sendmsg)struct file     *file;     
};

操作集辨析

?1.file_operations(struct file)?

??文件的通用操作接口??(如?readwritepoll

2.proto_ops(struct socket)

實現協議相關的系統調用??(如?bindconnectsendmsg

3.?struct proto(struct sock)

傳輸層協議的底層操作集

??recvfrom?函數聲明?

ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,struct sockaddr *src_addr,socklen_t *addrlen
);

參數詳解??

??參數????類型????說明??
sockfdint接受數據的套接字文件描述符(由?socket()?創建)。
bufvoid *接收數據的緩沖區地址,用于存儲接收到的數據。
lensize_t緩沖區的最大長度(字節數),防止緩沖區溢出。
flagsint控制接收行為的標志位(如?MSG_DONTWAITMSG_PEEK),通常設為?0
src_addrstruct sockaddr *接收發送方套接字地址結構體??的緩沖區
addrlensocklen_t *傳入緩沖區的大小,返回套接字地址結構體大小。

返回值??

??返回值????說明??
> 0成功接收到的字節數。
0??僅對 TCP 有效??,表示連接已關閉(UDP 不會返回?0)。
-1?(失敗)出錯,可通過?errno?獲取錯誤碼(如?EAGAIN?表示非阻塞模式下無數據)。

sendto函數

ssize_t sendto(int sockfd,                  // 套接字文件描述符const void *buf,            // 待發送數據的緩沖區size_t len,                 // 數據長度(字節數)int flags,                  // 發送方式控制標志(通常設為 0)const struct sockaddr *dest_addr,  // 目標地址結構體socklen_t addrlen           // 目標地址結構體長度
);

??參數解釋??

??參數????類型????說明??
sockfdint套接字文件描述符(由?socket()?創建)。
bufconst void *待發送數據的緩沖區地址。
lensize_t數據的長度(字節數)。
flagsint控制發送行為的標志位(如?MSG_DONTWAITMSG_MORE),通常設為?0
dest_addrconst struct sockaddr *??目標地址結構體??(如?struct sockaddr_in)。
addrlensocklen_tdest_addr?結構體的實際長度(如?sizeof(struct sockaddr_in))。

?返回值??

??返回值????說明??
> 0成功發送的字節數。
-1?(失敗)出錯,可通過?errno?獲取錯誤碼(如?EAGAIN?表示非阻塞模式下無法立即發送)。

udp服務器邏輯

1.利用socket函數創建套接字,傳參地址族和套接字類型,第三個參數是歷史遺留不用管,比如socket(AF_INET, SOCK_DGRAM, 0),說明套接字網絡層是ipv4,傳輸層是tcp,其底層就是創建struct file還有對應的struct socket和struct sock,然后返回套接字描述符

2.接下來要將套接字綁定端口,創建ipv4對應的套接字地址結構體struct sockaddr_in,然后填寫地址族AF_INET,再填寫端口號和ip地址,一般端口號是靠命令行參數來給出,IP地址則是INADDR_ANY,該套接字綁定的ip是任意的,也就是通過任何一個網卡接收都可以。

3.然后服務器死循環調用recvfrom,recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);,沒有數據則在套接字接收緩沖區等待隊列上阻塞等待

udp客戶端邏輯

1.命令行參數指明服務器端主機的任意一個網卡的ip地址,然后再指明端口,創建套接字socket(AF_INET, SOCK_DGRAM, 0);

2.用命令行參數準備好服務器通信套接字的地址結構體struct sockaddr_in,然后sendto發消息

udp發送消息過程分析

udp是沒有發送緩沖區的,只有接收緩沖區,客戶端調用sendto,會自動給套接字綁定端口,然后直接開始封裝udp報文,然后交給IP層(其實就是調用ip協議的接口),傳的參數就是udp報文和目標ip地址,ip層查路由表確定下一跳ip和發送網卡接口,封裝IP報頭,交給數據鏈路層處理(本質是調用以太網協議接口),傳參IP報文和下一跳ip和發送網卡接口,網卡驅動會先查arp緩存,得到下一跳ip的mac地址,然后給報文加上mac頭和crc校驗,寫進發送網卡對應的發送緩沖區,寫網卡的TDT寄存器通知,然后網卡會DMA將數據讀出,HVY轉換信號,接口發送出去,咱們假設客戶端是內網的一個主機,服務器部署在外網主機上,那這個下一跳很明顯是路由器,路由器的網卡接口收到信號后,HVY信號轉換,DMA寫進網卡的接收緩沖區,觸發硬件中斷,cpu陷入內核,執行中斷向量表中的中斷方法,網卡驅動將數據讀出,檢查mac地址,然后看幀類型是IP幀,于是進行crc校驗,沒有問題就去掉mac頭和crc校驗,交給ip層,然后IP頭的TTL減一,更改源ip為路由器的WAN口ip,并根據ip頭中的首部長度,總長度,上層協議類型這些字段將udp頭中的源port也改了(路由器除了維護路由表,還會維護地址轉換表來輔助NAT,地址轉換表里的對應關系是{源ip,源port,目的ip,目的port}和{改過的源ip,改過的源port,目的ip,目的端口}),改完后去查路由表確定下一跳ip和發送網卡,然后和之前一樣發出去,這次發到公網了,服務器收到后不斷解包到傳輸層(此時的底層應該是調用了udp協議的接口,將udp報文傳過去),然后udp層會根據udp頭里的端口拼出三元組{協議,目的ip,目的端口},然后根據OS維護的hash表找到對應udp套接字,將udp報文整個寫進該套接字的接收緩沖區,然后喚醒接收緩沖區等待隊列上的進程,recvfrom系統調用從接收緩沖區中讀出一個完整的udp報文,然后去掉報頭,將有效載荷寫進recvfrom函數參數傳來的的應用層緩沖區里,并填充參數傳來的套接字地址和其大小

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

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

相關文章

基于SD-WAN的管件制造數字化產線系統集成方案

1. 背景與目標隨著制造業向智能化、數字化方向轉型,傳統產線面臨著數據割裂、協同效率低下等問題。管件制造作為典型場景,涉及多環節的設計、制造與質檢流程,亟需一套高效的系統集成方案,保障全流程數據貫通與實時協同。本方案基于…

學習open62541 --- [79] 在docker中運行open62541工程

docker是非常流行的容器技術,解決了部署環境不一致的問題,open62541的工程也可以在docker容器中運行,本文講述如何把open62541工程放到docker容器中運行。 本文使用WSL ubuntu 22.04作為宿主環境,其它linux也是一樣。一 拉取debia…

Spring Boot微服務中集成gRPC實踐經驗分享

Spring Boot微服務中集成gRPC實踐經驗分享 一、業務場景描述 在某電商系統中,推薦服務、庫存服務、訂單服務等微服務需要高效、雙向流式通信,RESTHTTP已無法滿足低延遲、高并發和嚴格類型安全的需求。為此,我們選擇在Spring Boot微服務中集成…

springboot項目編寫測試類,亂碼問題解決

?MockMvc 的默認行為? MockMvc ?默認使用 ISO-8859-1 解碼響應,而服務端實際返回 UTF-8 編碼數據 。 Postman 無亂碼是因瀏覽器自動識別編碼,但 MockMvc 需顯式配置。 ?過濾器失效場景? Spring 的 CharacterEncodingFilter ?默認只對 POST 請求生效…

打破傳統,開啟 AR 智慧課堂?

在教育領域,AR 智慧課堂宛如一場及時雨,為傳統教育模式帶來了革命性的變革,讓學習變得更加生動有趣、高效互動。通過 AR 技術,抽象的知識瞬間變得鮮活起來,學生們可以在虛擬與現實交織的世界中,探索歷史的長…

熱烈祝賀 Flink 2.0 存算分離入選 VLDB 2025

VLDB 2025 論文熱烈祝賀 Apache Flink 2.0 的重磅研究成果《Disaggregated State Management in Apache Flink 2.0 》被數據庫領域頂級會議 VLDB 2025 正式接收!這項工作由 Apache Flink 社區 聯合 阿里巴巴實時計算 Flink 團隊 以及多位學術界研究人員共同完成&…

蓄電池能量管理matlab的simulink仿真

蓄電池能量管理matlab的simulink仿真模型 AlternatorTableData.mat , 7395 Battery_Management_Lib.mdl , 577258 Readme.txt , 1293 license.txt , 1551 ssc_battery_management.mdl , 221248 ssc_lead_acid_battery_50Ah_ini.m , 1760 ssc_lead_acid_battery_80Ah_ini.m , 1…

MyBatisPlus-03-擴展功能

文章目錄【README】【1】基于MyBatisPlus的代碼生成器【2】MyBatisPlus-DB靜態工具【2.1】使用MyBatisPlus的DB靜態工具查詢單個及多個用戶地址【查詢單個用戶的訪問效果】【查詢多個用戶的訪問效果】【3】邏輯刪除【3.1】代碼實現【4】枚舉處理器【4.1】代碼實現【5】JSON處理…

初識Neo4j之Cypher(三)

目錄 一、介紹 二、語法 1、節點 2、關系 3、屬性 4、模式 一、介紹 Cypher 是 Neo4j 的聲明式查詢語言,兼容 GQL 標準。通過 openCypher 項目,Cypher 以開源方式提供。它類似于 SQL,但專為圖數據優化。 Cypher 直觀且接近自然語言&…

19-C#靜態方法與靜態類

C#靜態方法與靜態類 1.static-靜態方法animal.eat();//直接調用 public class animal {public static void eat()//定義靜態方法{messagebox.show("animal eat");} }2.static-靜態類animal.eat();//直接調用public stat…

基于YOLO的足球檢測Web應用:從訓練到部署的完整實戰

用Python和深度學習技術打造一個完整的足球檢測系統,支持圖片檢測、視頻分析和實時監控。本文帶你從零開始構建一個專業的Web應用。🎯 項目背景 在體育賽事分析和足球訓練中,準確識別和定位足球是一個重要需求。本項目利用YOLO深度學習算法&a…

npm 切換 node 版本 和npm的源

在開發過程中,不同項目可能需要不同版本的 Node.js,同時 于由XX原因,我們需要切換npm的源。這時如果需要切換node版本或者npm的源,我們可以使用以下方法。 使用 nvm 切換 Node 版本 1、安裝 npm install nvm -g2、使用 # 列出所有…

Java學習第二十部分——EasyMock

目錄 一.概述 二.作用 三.工作原理 四.使用示例 五.主要特點 六.適用場景 七.其他模擬框架比較 八.idea簡單項目實戰 1.打開idea創建Java項目,注意構建系統選“Maven” 2.為pom.xml文件添加如下依賴,并重新加載Maven依賴,直至不報錯…

機器學習模型在C++平臺的部署

一、概述機器學習模型的訓練通常在Python環境下完成,而現實生產環境的復雜性和多樣性使得模型的部署成為一個值得關注的重點。不同應用場景下有不同適應的實現方式,這里主要介紹通過一種通用中間格式——ONNX(Open Neural Network Exchange&a…

保姆級安裝 Ruby 環境下載及安裝教程, RubyInstaller下載及安裝教程

一、下載安裝 RubyInstaller 1.打開 RubyInstaller 官網:https://rubyinstaller.org/ 點擊跳轉, 官網界面如下圖: 點擊下載最新的 RubyDevkit 版本(如 RubyDevkit 3.4.X (x64) )。如下圖所示: 注意點:如果…

SQL 一鍵生成 Go Struct!支持字段注釋、類型映射、結構體命名規范

SQL 一鍵生成 Go Struct!支持字段注釋、類型映射、結構體命名規范 在 Golang 開發中,尤其是操作數據庫時,我們經常會遇到這種場景: ? 拿到數據庫建表 SQL,卻要手動寫 Go struct? 字段幾十個、類型復雜,…

Web 前端框架選型:React、Vue 和 Angular 的對比與實踐

Web 前端框架選型:React、Vue 和 Angular 的對比與實踐 選擇前端框架就像選擇一個長期合作伙伴。錯誤的選擇可能會讓你的項目在未來幾年內背負沉重的技術債務,而正確的選擇則能讓開發效率飛速提升。 經過多年的項目實踐,我發現很多新人在框架…

C# 值拷貝、引用拷貝、淺拷貝、深拷貝

值拷貝定義:直接復制變量的值,適用于基本數據類型(如int, float, char等)。在 C# 中,值類型(基本數據類型和結構體)默認使用值拷貝。特點:創建原始值的完全獨立副本,修改…

深度學習圖像分類數據集—百種鳥類識別分類

該數據集為圖像分類數據集,適用于ResNet、VGG等卷積神經網絡,SENet、CBAM等注意力機制相關算法,Vision Transformer等Transformer相關算法。 數據集信息介紹:525種鳥類識別分類 訓練數據集總共有84635張圖片,每個文件夾…

零基礎 “入坑” Java--- 八、類和對象(一)

文章目錄一、初識面向對象二、類的定義和使用1.認識類2.類的定義格式三、類的實例化四、this引用五、對象的構造及初始化1.有關初始化2.構造方法3.就地初始化一、初識面向對象 Java是一門純面向對象的語言(OOP),在面向對象的世界里&#xff…