【C++網絡編程】第5篇:UDP與廣播通信

一、UDP協議核心特性

1. UDP vs TCP

?特性 ?UDP?TCP
連接方式無連接面向連接(三次握手)
可靠性不保證數據到達或順序可靠傳輸(超時重傳、順序控制)
傳輸效率低延遲,高吞吐相對較低(因握手和確認機制)
適用場景實時音視頻、廣播、在線游戲文件傳輸、Web請求、數據庫操作

2. UDP數據包結構

  • **首部(8字節)**?:
| 源端口(2) | 目標端口(2) |
| 數據包長度(2) | 校驗和(2) |
  • 數據載荷:最大長度受限于IPv4的MTU(通常1500字節)?。

3. 不同方式介紹

?單播(Unicast)?:1 對 1(普通 UDP/TCP 通信)。
?廣播(Broadcast)?:1 對同一子網內所有設備。
?組播(Multicast)?:1 對一組指定的設備(跨子網)。


二、UDP單播通信實現

1. UDP服務器與客戶端流程

服務器:socket() → bind() → recvfrom() → sendto()
客戶端:socket() → sendto() → recvfrom()

2. 完整代碼示例

?UDP服務器(接收并回復)?

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>  
#pragma comment(lib, "ws2_32.lib")int main() {WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "WSAStartup failed!" << std::endl;return 1;}SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);sockaddr_in serverAddr{};serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);serverAddr.sin_port = htons(8080);bind(sock, (sockaddr*)&serverAddr, sizeof(serverAddr));std::cout << "UDP Server listening on port 8080..." << std::endl;char buffer[1024];sockaddr_in clientAddr{};int clientAddrLen = sizeof(clientAddr);while (true) {int bytesReceived = recvfrom(sock, buffer, sizeof(buffer), 0,(sockaddr*)&clientAddr, &clientAddrLen);if (bytesReceived == SOCKET_ERROR) {std::cerr << "recvfrom failed: " << WSAGetLastError() << std::endl;continue;}char clientIp[INET_ADDRSTRLEN] = { 0 };if (InetNtopA(AF_INET,                            // IPv4&clientAddr.sin_addr,               // 輸入地址結構體clientIp,                           // 輸出緩沖區sizeof(clientIp)                    // 緩沖區大小) == NULL) {std::cerr << "IP conversion failed: " << WSAGetLastError() << std::endl;strcpy_s(clientIp, "unknown");      // 錯誤時顯示 "unknown"}std::cout << "Received " << bytesReceived << " bytes from "<< clientIp << ":"                  // 使用轉換后的 IP 字符串<< ntohs(clientAddr.sin_port) << std::endl;// 原樣返回數據sendto(sock, buffer, bytesReceived, 0,(sockaddr*)&clientAddr, clientAddrLen);}closesocket(sock);WSACleanup();return 0;
}

UDP客戶端(發送消息)?

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h> 
#pragma comment(lib, "ws2_32.lib")int main() {WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "WSAStartup failed!" << std::endl;return 1;}SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);sockaddr_in serverAddr{};serverAddr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &(serverAddr.sin_addr.s_addr));serverAddr.sin_port = htons(8080);const char* message = "Hello UDP Server!";sendto(sock, message, strlen(message), 0,(sockaddr*)&serverAddr, sizeof(serverAddr));char buffer[1024];int bytesReceived = recvfrom(sock, buffer, sizeof(buffer), 0, nullptr, nullptr);if (bytesReceived > 0) {std::cout << "Server echoed: " << std::string(buffer, bytesReceived) << std::endl;}closesocket(sock);WSACleanup();return 0;
}

測試結果
在這里插入圖片描述


三、UDP廣播通信

1. 廣播地址與設置

  • 廣播地址:255.255.255.255(全局廣播)或子網廣播地址(如192.168.1.255)。
  • ?套接字選項:啟用SO_BROADCAST
int enable = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(enable));

2. 廣播發送端代碼

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>  
#pragma comment(lib, "ws2_32.lib")int main() {WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "WSAStartup failed!" << std::endl;return 1;}SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);// 啟用廣播int enable = 1;setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(enable));sockaddr_in broadcastAddr{};broadcastAddr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &(broadcastAddr.sin_addr.s_addr));broadcastAddr.sin_port = htons(8080);const char* message = "Broadcast Message!";sendto(sock, message, strlen(message), 0,(sockaddr*)&broadcastAddr, sizeof(broadcastAddr));closesocket(sock);WSACleanup();return 0;
}

3. 服務器端修改部分

        std::cout << "Received " << bytesReceived << " bytes from "<< clientIp << ":"                  // 使用轉換后的 IP 字符串<< ntohs(clientAddr.sin_port) << std::endl;std::cout << "Datas:" << std::string(buffer, bytesReceived) << std::endl;

4. 測試結果

在這里插入圖片描述


四、UDP組播(Multicast)?

1. 組播地址范圍

  • IPv4:224.0.0.0 ~ 239.255.255.255(如239.255.0.1)。

2. 接收端

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")int main() {WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "WSAStartup failed!" << std::endl;return 1;}// 創建 UDP 套接字SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sock == INVALID_SOCKET) {std::cerr << "socket() failed: " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 設置端口復用(允許其他進程綁定相同端口)int reuse = 1;if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,(char*)&reuse, sizeof(reuse)) == SOCKET_ERROR) {std::cerr << "setsockopt(SO_REUSEADDR) failed: " << WSAGetLastError() << std::endl;closesocket(sock);WSACleanup();return 1;}// 綁定到本地端口sockaddr_in localAddr{};localAddr.sin_family = AF_INET;localAddr.sin_addr.s_addr = htonl(INADDR_ANY);localAddr.sin_port = htons(8080);if (bind(sock, (sockaddr*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) {std::cerr << "bind() failed: " << WSAGetLastError() << std::endl;closesocket(sock);WSACleanup();return 1;}// 加入組播組ip_mreq mreq{};if (inet_pton(AF_INET, "239.255.255.250", &(mreq.imr_multiaddr.s_addr)) != 1) {std::cerr << "inet_pton() failed for multicast address" << std::endl;closesocket(sock);WSACleanup();return 1;}mreq.imr_interface.s_addr = htonl(INADDR_ANY);  // 使用默認網絡接口if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&mreq, sizeof(mreq)) == SOCKET_ERROR) {std::cerr << "setsockopt(IP_ADD_MEMBERSHIP) failed: " << WSAGetLastError() << std::endl;closesocket(sock);WSACleanup();return 1;}std::cout << "Listening for multicast on 239.255.255.250:8080..." << std::endl;char buffer[1024];sockaddr_in senderAddr{};int senderAddrLen = sizeof(senderAddr);while (true) {// 接收數據int bytesReceived = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,(sockaddr*)&senderAddr, &senderAddrLen);if (bytesReceived == SOCKET_ERROR) {std::cerr << "recvfrom() failed: " << WSAGetLastError() << std::endl;continue;}// 顯示來源信息char senderIp[INET_ADDRSTRLEN] = { 0 };inet_ntop(AF_INET, &senderAddr.sin_addr, senderIp, INET_ADDRSTRLEN);std::cout << "Received " << bytesReceived << " bytes from "<< senderIp << ":" << ntohs(senderAddr.sin_port) << std::endl;// 安全處理數據(防止緩沖區溢出)buffer[bytesReceived] = '\0';  // 添加字符串終止符std::cout << "Data: " << buffer << std::endl;}// 退出時清理(雖然 while(true) 會阻止執行到這里)closesocket(sock);WSACleanup();return 0;
}

3. 發送端

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")int main() {// 初始化 WinsockWSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "WSAStartup failed: " << WSAGetLastError() << std::endl;return 1;}// 創建 UDP 套接字SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sock == INVALID_SOCKET) {std::cerr << "socket() failed: " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 設置組播 TTL(控制傳輸范圍)int ttl = 32;if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,(char*)&ttl, sizeof(ttl)) == SOCKET_ERROR) {std::cerr << "setsockopt(IP_MULTICAST_TTL) failed: " << WSAGetLastError() << std::endl;closesocket(sock);WSACleanup();return 1;}// 構建組播目標地址sockaddr_in multicastAddr{};multicastAddr.sin_family = AF_INET;multicastAddr.sin_port = htons(8080); // 目標端口// 轉換組播地址if (inet_pton(AF_INET, "239.255.255.250", &multicastAddr.sin_addr.s_addr) != 1) {std::cerr << "inet_pton() failed for multicast address" << std::endl;closesocket(sock);WSACleanup();return 1;}// 發送數據const char* msg = "Hello Multicast!";int msgLen = static_cast<int>(strlen(msg));int bytesSent = sendto(sock, msg, msgLen, 0,(sockaddr*)&multicastAddr, sizeof(multicastAddr));if (bytesSent == SOCKET_ERROR) {std::cerr << "sendto() failed: " << WSAGetLastError() << std::endl;}else if (bytesSent != msgLen) {std::cerr << "sendto() partial send: " << bytesSent << "/" << msgLen << std::endl;}else {std::cout << "Successfully sent " << bytesSent<< " bytes to multicast group 239.255.255.250:8080" << std::endl;}// 清理資源closesocket(sock);WSACleanup();return 0;
}

4. 測試結果

在這里插入圖片描述


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

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

相關文章

MOSN(Modular Open Smart Network)是一款主要使用 Go 語言開發的云原生網絡代理平臺

前言 大家好&#xff0c;我是老馬。 sofastack 其實出來很久了&#xff0c;第一次應該是在 2022 年左右開始關注&#xff0c;但是一直沒有深入研究。 最近想學習一下 SOFA 對于生態的設計和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概覽 SOFABoot-01-螞蟻金服開源的 s…

微信小程序日常開發問題整理

微信小程序日常開發問題整理 1 切換渲染模式1.1 WebView 的鏈接在模擬器可以打開&#xff0c;手機上無法打開。 1 切換渲染模式 1.1 WebView 的鏈接在模擬器可以打開&#xff0c;手機上無法打開。 在 app.json 中看到如下配置項&#xff0c;那么當前項目就是 keyline 渲染模式…

【Altium Designer】銅皮編輯

一、動態銅皮與靜態銅皮的區分與切換 動態銅皮&#xff08;活銅&#xff09;&#xff1a; 通過快捷鍵 PG 創建&#xff0c;支持自動避讓其他網絡對象&#xff0c;常用于大面積鋪銅&#xff08;如GND或電源網絡&#xff09;。修改動態銅皮后&#xff0c;需通過 Tools → Polygo…

Java「Deque」 方法詳解:從入門到實戰

Java Deque 各種方法解析&#xff1a;從入門到實戰 在 Java 編程中&#xff0c;Deque&#xff08;雙端隊列&#xff09;是一個功能強大的數據結構&#xff0c;允許開發者從隊列的兩端高效地添加、刪除和檢查元素。作為 java.util 包中的一部分&#xff0c;Deque 接口繼承自 Qu…

ffmpeg+QOpenGLWidget顯示視頻

?一個基于 ?FFmpeg 4.x? 和 QOpenGLWidget的簡單視頻播放器代碼示例&#xff0c;實現視頻解碼和渲染到 Qt 窗口的功能。 1&#xff09;ffmpeg庫界面&#xff0c;視頻解碼支持軟解和硬解方式。 硬解后&#xff0c;硬件解碼完成需要將數據從GPU復制到CPU。優先采用av_hwf…

深入解析嵌入式內核:從架構到實踐

一、嵌入式內核概述 嵌入式內核是嵌入式操作系統的核心組件&#xff0c;負責管理硬件資源、調度任務、處理中斷等關鍵功能。其核心目標是在資源受限的環境中提供高效、實時的控制能力。與通用操作系統不同&#xff0c;嵌入式內核通常具有高度可裁剪性、實時性和可靠性&#xff…

20250324-使用 `nltk` 的 `sent_tokenize`, `word_tokenize、WordNetLemmatizer` 方法時報錯

解決使用 nltk 的 sent_tokenize, word_tokenize、WordNetLemmatizer 方法時報錯問題 第 2 節的手動方法的法1可解決大部分問題&#xff0c;可首先嘗試章節 2 的方法 1. nltk.download(‘punkt_tab’) LookupError: *******************************************************…

『 C++ 』多線程同步:條件變量及其接口的應用實踐

文章目錄 條件變量概述條件變量簡介條件變量的基本用法 案例&#xff1a;兩個線程交替打印奇偶數代碼解釋 std::unique_lock::try_lock_until 介紹代碼示例代碼解釋注意事項 std::condition_variable::wait 詳細解析與示例std::condition_variable::wait 接口介紹代碼示例代碼解…

【VolView】純前端實現CT三維重建-CBCT

文章目錄 什么是CBCTCBCT技術路線使用第三方工具使用Python實現使用前端實現 純前端實現方案優缺點使用VolView實現CBCT VolView的使用1.克隆代碼2.配置依賴3.運行4.效果 進階&#xff1a;VolView配合Python解決卡頓1.修改VtkThreeView.vue2.新增Custom3DView.vue3.Python生成s…

debug - 安裝.msi時,為所有用戶安裝程序

文章目錄 debug - 安裝.msi時&#xff0c;為所有用戶安裝程序概述筆記試試在目標.msi后面直接加參數的測試 備注備注END debug - 安裝.msi時&#xff0c;為所有用戶安裝程序 概述 為了測試&#xff0c;裝了一個test.msi. 安裝時&#xff0c;只有安裝路徑的選擇&#xff0c;沒…

Java Stream兩種list判斷字符串是否存在方案

這里寫自定義目錄標題 背景初始化方法一、filter過濾方法二、anyMatch匹配 背景 在項目開發中&#xff0c;經常遇到篩選list中是否包含某個子字符串&#xff0c;有多種方式&#xff0c;本篇主要介紹stream流的filter和anyMatch兩種方案&#xff0c;記錄下來&#xff0c;方便備…

DeepSeek vs 通義大模型:誰將主導中國AI的未來戰場?

當你在深夜調試代碼時,是否幻想過AI伙伴能真正理解你的需求?當企業面對海量數據時,是否期待一個真正智能的決策大腦? 這場由DeepSeek和通義領銜的大模型之爭,正在重塑中國AI產業的競爭格局。本文將為你揭開兩大技術巨頭的終極對決! 一、顛覆認知的技術突破 1.1 改變游戲…

3. 軸指令(omron 機器自動化控制器)——>MC_SetOverride

機器自動化控制器——第三章 軸指令 12 MC_SetOverride變量?輸入變量?輸出變量?輸入輸出變量 功能說明?時序圖?重啟運動指令?多重啟動運動指令?異常 MC_SetOverride 變更軸的目標速度。 指令名稱FB/FUN圖形表現ST表現MC_SetOverride超調值設定FBMC_SetOverride_instan…

從像素到世界:自動駕駛視覺感知的坐標變換體系

接著上一篇 如何讓自動駕駛汽車“看清”世界?坐標映射與數據融合詳解的概述,這一篇詳細講解自動駕駛多目視覺系統設計原理,并給出應用示例。 摘要 在自動駕駛系統中,準確的環境感知是實現路徑規劃與決策控制的基礎。本文系統性地解析圖像坐標系、像素坐標系、相機坐標系與…

附錄B ISO15118-20測試命令

本章節給出ISO15118-20協議集的V2G命令&#xff0c;包含json、xml&#xff0c;并且根據exiCodec.jar編碼得到exi內容&#xff0c; 讀者可以參考使用&#xff0c;測試編解碼庫是否能正確編解碼。 B.1 supportedAppProtocolReq json: {"supportedAppProtocolReq": {…

VLAN章節學習

為什么會有vlan這個技術&#xff1f; 1.通過劃分廣播域來降低廣播風暴導致的設備性能下降&#xff1b; 2.提高網絡管理的靈活性和通過隔離網絡帶來的安全性&#xff1b; 3.在成本不變的情況下增加更多的功能性&#xff1b; VLAN又稱虛擬局域網&#xff08;再此擴展&#xf…

FPGA時鐘約束

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 目錄 前言 一、Create_clock 前言 時鐘周期約束&#xff0c;就是對時鐘進行約束。 一、Create_clock create_clock -name <name> -period <period> -waveform …

機房布局和布線的最佳實踐:如何打造高效、安全的機房環境

機房布局和布線的最佳實踐:如何打造高效、安全的機房環境 大家好,我是Echo_Wish。今天我們來聊聊機房布局和布線的問題,這可是數據中心和IT運維中的一個非常重要的環節。不管是剛剛接觸運維的新人,還是已經摸爬滾打多年的老兵,都應該對機房的布局和布線有一個清晰的認識。…

spring-security原理與應用系列:建造者

目錄 1.構建過程 AbstractSecurityBuilder AbstractConfiguredSecurityBuilder WebSecurity 2.建造者類圖 SecurityBuilder ???????AbstractSecurityBuilder ???????AbstractConfiguredSecurityBuilder ???????WebSecurity 3.小結 緊接上一篇文…

OpenHarmony子系統開發 - 電池管理(二)

OpenHarmony子系統開發 - 電池管理&#xff08;二&#xff09; 五、充電限流限壓定制開發指導 概述 簡介 OpenHarmony默認提供了充電限流限壓的特性。在對終端設備進行充電時&#xff0c;由于環境影響&#xff0c;可能會導致電池溫度過高&#xff0c;因此需要對充電電流或電…