UDP 多點通信

一、setsockopt/getsockopt 函數詳解

1. 函數原型

c

#include <sys/socket.h>
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

2. 功能
  • setsockopt:設置套接字選項(修改網絡屬性)。
  • getsockopt:獲取套接字選項(查詢網絡屬性)。
3. 參數說明
參數描述
sockfd套接字文件描述符
level協議層級:
SOL_SOCKET(通用選項)
IPPROTO_IP(IP 層選項)
IPPROTO_UDP(UDP 層選項)
optname選項名稱(依賴于level
optval選項值(指針類型,具體類型取決于optname
optlenoptval的字節長度(getsockopt需傳入指針,setsockopt需傳入值)
4. 常用選項及示例
4.1 SOL_SOCKET 層級
  • SO_REUSEADDR:允許重用本地地址和端口(解決端口占用問題)。

    c

    int optval = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    
  • SO_BROADCAST:允許發送廣播數據(僅 UDP 可用)。

    c

    int optval = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)); // 發送方需設置
    
  • SO_RCVTIMEO/SO_SNDTIMEO:設置接收 / 發送超時時間(struct timeval類型)。

    c

    struct timeval timeout = {3, 0}; // 3秒超時
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    
4.2 IPPROTO_IP 層級(組播相關)
  • IP_ADD_MEMBERSHIP:加入組播組。

    c

    struct ip_mreqn mreq;
    mreq.imr_multiaddr.s_addr = inet_addr("224.1.2.3"); // 組播IP
    mreq.imr_address.s_addr = inet_addr("192.168.1.100"); // 本地IP
    mreq.imr_ifindex = 0; // 網絡接口索引(0表示自動選擇)
    setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
    
  • IP_DROP_MEMBERSHIP:退出組播組(參數同IP_ADD_MEMBERSHIP)。
4.3 IPPROTO_TCP 層級
  • TCP_NODELAY:禁用 Nagle 算法(提升實時性)。

    c

    int optval = 1;
    setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
    

二、UDP 多點通信

1. 廣播通信(Broadcast)
  • 特點

    • 一對多通信,數據發送到局域網內所有主機。
    • 廣播地址示例:192.168.1.255(網絡號 + 全 1 主機號)或255.255.255.255(受限廣播)。
    • 僅 UDP 支持,數據不可跨路由器。
  • 實現步驟

    廣播接收者(UDP 服務器)
    1. 創建 UDP 套接字:socket(AF_INET, SOCK_DGRAM, 0)
    2. 綁定廣播地址(如192.168.1.2550.0.0.0)。

      c

      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(8888);
      addr.sin_addr.s_addr = inet_addr("192.168.1.255");
      bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
      
    3. 接收數據:recvfrom()
    廣播發送者(UDP 客戶端)
    1. 創建 UDP 套接字。
    2. 設置SO_BROADCAST選項。
    3. 發送數據到廣播地址:sendto()

      c

      int optval = 1;
      setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
      struct sockaddr_in dest_addr;
      dest_addr.sin_family = AF_INET;
      dest_addr.sin_port = htons(8888);
      dest_addr.sin_addr.s_addr = inet_addr("192.168.1.255");
      sendto(sockfd, "Hello", 5, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
      
2. 組播通信(Multicast)
  • 特點

    • 一對一組通信,僅加入組播組的主機可接收數據。
    • 組播 IP 范圍:224.0.0.0~239.255.255.255
    • 需通過IP_ADD_MEMBERSHIP加入組播組。
  • 實現步驟

    組播接收者(UDP 服務器)
    1. 創建 UDP 套接字。
    2. 加入組播組:setsockopt()設置IP_ADD_MEMBERSHIP
    3. 綁定組播 IP 和端口(或綁定0.0.0.0接收所有組播數據)。

      c

      struct ip_mreqn mreq;
      mreq.imr_multiaddr.s_addr = inet_addr("224.1.2.3");
      mreq.imr_address.s_addr = INADDR_ANY; // 本地IP設為任意
      setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(8888);
      addr.sin_addr.s_addr = INADDR_ANY; // 綁定任意IP
      bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
      
    組播發送者(UDP 客戶端)
    1. 創建 UDP 套接字。
    2. 直接發送數據到組播 IP:sendto()

      c

      struct sockaddr_in dest_addr;
      dest_addr.sin_family = AF_INET;
      dest_addr.sin_port = htons(8888);
      dest_addr.sin_addr.s_addr = inet_addr("224.1.2.3");
      sendto(sockfd, "Hello", 5, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
      

三、關鍵對比

特性廣播(Broadcast)組播(Multicast)
地址范圍局域網內所有主機(如192.168.1.255組播組(如224.1.2.3
網絡層支持依賴鏈路層廣播依賴 IP 組播協議
跨路由不可跨路由可通過配置跨路由(需路由器支持)
資源消耗高(所有主機接收)低(僅組成員接收)
適用場景局域網內通知(如 DHCP)實時流媒體、在線會議(如視頻直播)

四、代碼示例:UDP 廣播聊天

1. 廣播接收者(服務器)

c

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>#define PORT 8888
#define BUF_SIZE 128int main() {// 創建UDP套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) { perror("socket error"); return -1; }// 允許端口重用int optval = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));// 綁定廣播地址struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = inet_addr("192.168.1.255"); // 或 INADDR_BROADCASTif (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {perror("bind error"); return -1;}// 接收廣播數據char buf[BUF_SIZE] = {0};struct sockaddr_in cli_addr;socklen_t cli_len = sizeof(cli_addr);while (1) {ssize_t n = recvfrom(sockfd, buf, BUF_SIZE-1, 0, (struct sockaddr*)&cli_addr, &cli_len);if (n > 0) {buf[n] = '\0';printf("Received: %s\n", buf);}}close(sockfd);return 0;
}
2. 廣播發送者(客戶端)

c

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>#define PORT 8888
#define BUF_SIZE 128int main() {// 創建UDP套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) { perror("socket error"); return -1; }// 允許發送廣播int optval = 1;setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));// 廣播地址struct sockaddr_in dest_addr;memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(PORT);dest_addr.sin_addr.s_addr = inet_addr("192.168.1.255");// 發送數據char buf[BUF_SIZE] = {0};while (fgets(buf, BUF_SIZE, stdin)) {buf[strcspn(buf, "\n")] = 0; // 去除換行符sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));memset(buf, 0, BUF_SIZE);}close(sockfd);return 0;
}

五、總結

  • setsockopt/getsockopt:是網絡編程中配置套接字行為的核心函數,通過不同層級和選項可實現端口重用、超時控制、組播加入等高級功能。
  • UDP 廣播:適用于局域網內的一對多通信,但存在廣播風暴風險,且無法跨路由。
  • UDP 組播:通過組播組實現高效的一對多通信,節省網絡資源,適合實時數據傳輸。
  • 注意事項
    • 廣播發送方需設置SO_BROADCAST選項,接收方需綁定廣播地址。
    • 組播接收方需通過IP_ADD_MEMBERSHIP加入組播組,發送方直接向組播 IP 發送數據。

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

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

相關文章

說一說Node.js高性能開發中的I/O操作

眾所周知&#xff0c;在軟件開發的領域中&#xff0c;輸入輸出&#xff08;I/O&#xff09;操作是程序與外部世界交互的重要環節&#xff0c;比如從文件讀取數據、向網絡發送請求等。這段時間&#xff0c;也指導項目中一些項目的開發工作&#xff0c;發現在Node.js運用中&#…

Charles抓包并破解ProtoBuf請求

安裝Charles并抓包 如果是外網的需要root安裝一系列證書等&#xff0c;詳細見參考文章&#xff1a; 在雷電模擬器安卓7.0上使用Charles抓包詳細教程 遇到如下問題&#xff1a; 1.粘貼到目錄/system/etc/security/cacerts內&#xff0c;粘貼不了。需要打開這個 2.模擬器wifi打…

Odoo 18 安全組與訪問權限管理指南

Odoo 18 安全組與訪問權限管理指南 一、準備工作&#xff1a;在自定義模塊中創建安全配置文件 創建 security 文件夾 在自定義模塊內創建名為 security 的文件夾&#xff0c;用于存放安全組和訪問權限的定義文件。 二、定義模型訪問權限&#xff1a;ir.model.access.csv 文…

使用lldb查看Rust不同類型的結構

目錄 前言 正文 標量類型 復合類型——元組 復合類型——數組 函數 &str struct 可變數組vec Iter String Box Rc Arc RefCell Mutex RwLock Channel 總結 前言 筆者發現這個lldb挺好玩的&#xff0c;可以查看不同類型的結構&#xff0c;雖然這好像是C的東…

uniapp使用ui.request 請求流式輸出

正文&#xff1a; 在現代Web開發中&#xff0c;實時數據流和長時間運行的請求變得越來越常見&#xff0c;尤其是在處理大量數據或進行實時通信時。在這種情況下&#xff0c;uniapp 提供的 ui.request 請求方法可以幫助我們輕松實現流式輸出請求。本文將介紹如何使用 uni.reques…

如何恢復被勒索軟件加密的服務器文件(解密與備份策略)

針對勒索軟件加密文件的恢復和解密策略&#xff0c;結合當前數據安全最佳實踐&#xff0c;整理應對指南如下&#xff1a; 一、文件解密與修復方法 立即隔離設備? 斷開網絡連接并禁用共享功能&#xff0c;防止病毒橫向傳播 通過文件后綴異常&#xff08;如.locked、.wxx&…

JS,ES,TS三者什么區別

Java Script(JS)、ECMAScript(ES)、TypeScript(TS) 的核心區別與關聯的詳細解析,結合技術背景、設計目標及應用場景展開說明: 一、核心定義與關系 JavaScript(JS) 定義:一種動態類型、基于原型的腳本語言,由 Netscape 公司于 1995 年首次開發,用于網頁交互功能。角…

【MapReduce入門】深度解析MapReduce:定義、核心特點、優缺點及適用場景

目錄 1 什么是MapReduce&#xff1f; 2 MapReduce的核心特點 2.1 分布式處理 2.2 容錯機制 3 MapReduce的完整工作流程 4 MapReduce的優缺點分析 4.1 優勢 4.2 局限性 5 MapReduce典型應用場景 5.1 適用場景 5.2 不適用場景 6 MapReduce與其他技術的對比 7 總結 1…

【Redis】分布式鎖的實現

目錄 一、本地鎖存在的問題 二、redis實現分布式鎖原理 三、使用示例 四、鎖誤刪問題 解決思路 獲取鎖和釋放鎖代碼優化 五、鎖釋放的原子性問題 解決思路&#xff08;Lua腳本&#xff09; 使用流程 總結 大家好&#xff0c;我是千語。上期給大家講了使用悲觀鎖來解決…

Unity3D對象池設計與實現詳解

前言 在Unity3D中&#xff0c;對象池&#xff08;Object Pooling&#xff09;是一種優化技術&#xff0c;用于減少頻繁實例化和銷毀對象帶來的性能開銷。以下是對象池的詳細設計和實現步驟&#xff1a; 對惹&#xff0c;這里有一個游戲開發交流小組&#xff0c;希望大家可以點…

[Spring]-組件的生命周期

組件生命周期 認識組件的聲明周期 實驗1 通過Bean指定組件的生命周期 package com.guigu.spring.ioc.bean;Data public class User {private String username;private String password;private Car car;Autowiredpublic void setCar(Car car) {System.out.println("自動…

【golang】網絡數據包捕獲庫 gopacket

詳解 github.com/google/gopacket/pcap 包 github.com/google/gopacket/pcap 是 Go 語言中一個強大的網絡數據包捕獲庫&#xff0c;它是 gopacket 項目的一部分&#xff0c;提供了對 libpcap&#xff08;Linux/Unix&#xff09;和 WinPcap&#xff08;Windows&#xff09;的 G…

RBTree的模擬實現

1&#xff1a;紅黑樹的概念 紅?樹是?棵?叉搜索樹&#xff0c;他的每個結點增加?個存儲位來表?結點的顏?&#xff0c;可以是紅?或者??。通過對任何?條從根到葉?的路徑上各個結點的顏?進?約束&#xff0c;紅?樹確保沒有?條路徑會?其他路徑?出2倍&#xff0c;因…

React 第三十九節 React Router 中的 unstable_usePrompt Hook的詳細用法及案例

React Router 中的 unstable_usePrompt 是一個用于在用戶嘗試離開當前頁面時觸發確認提示的自定義鉤子&#xff0c;常用于防止用戶誤操作導致數據丟失&#xff08;例如未保存的表單&#xff09;。 一、unstable_usePrompt用途 防止意外離開頁面&#xff1a;當用戶在當前頁面有…

OSI 7層模型

OSI 7層模型&#xff1a; 1、物理層&#xff08;光纖等把電腦連接起來的物理手段&#xff09; 2、數據鏈路層&#xff08;以太網&#xff0c;確認0和1電信號的分組方式&#xff0c;負責MAC地址&#xff0c;MAC地址用于在網絡中唯一標示一個網卡&#xff0c;相當于網卡的身份證…

視頻編解碼學習十一之視頻原始數據

一、視頻未編碼前的原始數據是怎樣的&#xff1f; 視頻在未編碼前的原始數據被稱為 原始視頻數據&#xff08;Raw Video Data&#xff09;&#xff0c;主要是按照幀&#xff08;Frame&#xff09;來組織的圖像序列。每一幀本質上就是一張圖片&#xff0c;通常采用某種顏色格式…

Redis學習打卡-Day1-SpringDataRedis、有狀態無狀態

Redis的Java客戶端 Jedis 以 Redis 命令作為方法名稱&#xff0c;學習成本低&#xff0c;簡單實用。Jedis 是線程不安全的&#xff0c;并且頻繁的創建和銷毀連接會有性能損耗&#xff0c;因此推薦使用 Jedis 連接池代替Jedis的直連方式。 lettuce Lettuce是基于Netty實現的&am…

告別靜態配置!Spring Boo動態線程池實戰指南:Nacos+Prometheus全鏈路監控

一、引言 1.1 動態線程池的必要性 傳統線程池的參數&#xff08;如核心線程數、隊列容量&#xff09;通常通過配置文件靜態定義&#xff0c;無法根據業務負載動態調整。例如&#xff0c;在電商大促場景中&#xff0c;流量可能瞬間激增&#xff0c;靜態線程池容易因配置不合理導…

Flask如何讀取配置信息

目錄 一、使用 app.config 讀取配置 二、設置配置的幾種方式 1. 直接設置 2. 從 Python 文件加載 3. 從環境變量加載 4. 從字典加載 5. 從 .env 文件加載&#xff08;推薦開發環境用&#xff09; 三、讀取配置值 四、最佳實踐建議 在 Flask 中讀取配置信息有幾種常見方…

【React中useCallback鉤子詳解】

useCallback 是 React 中的一個性能優化 Hook,用于緩存函數引用,避免在組件重新渲染時重復創建相同的函數,從而減少不必要的子組件渲染或副作用執行。以下是其核心要點: 1. 核心作用 函數記憶化:返回一個記憶化的回調函數,僅在依賴項變化時重新創建函數,否則復用之前的函…