刷題
| # UDP多點通信核心要點 |
| |
| ## 基礎通信模式 |
| ### 單播通信 |
| - 一對一通信方式 |
| - UDP默認通信模式 |
| - 地址指向具體目標主機 |
| |
| ### 廣播通信 |
| - 一對多通信機制 |
| - 地址范圍:`xxx.xxx.xxx.255` |
| - 僅限局域網傳輸 |
| - 需設置SO_BROADCAST標志 |
| |
| ### 組播通信 |
| - 多對多群組通信 |
| - 地址范圍:224.0.0.0~239.255.255.255 |
| - 需加入組播IP(IP_ADD_MEMBERSHIP) |
| |
| ## 核心函數配置 |
| ### setsockopt參數 |
| #### 通用配置 |
| - `SO_REUSEADDR`:端口復用 |
| - `SO_RCVTIMEO`:接收超時 |
| - `SO_SNDTIMEO`:發送超時 |
| |
| #### 廣播配置 |
| - `SO_BROADCAST`:廣播權限 |
| - 綁定地址:`255.255.255.255` |
| |
| #### 組播配置 |
| - `IP_ADD_MEMBERSHIP`:加入組播 |
| - `struct ip_mreqn`結構體: |
| ```c |
| struct ip_mreqn { |
| struct in_addr imr_multiaddr; // 組播IP |
| struct in_addr imr_address; // 本地IP |
| int imr_ifindex; // 網絡接口索引 |
| }; |
通信實現邏輯
廣播服務器
- 創建DGRAM套接字
- 綁定廣播地址或
0.0.0.0
- 設置
SO_REUSEADDR
- 循環接收數據
組播客戶端
- 創建DGRAM套接字
- 加入組播組(IP_ADD_MEMBERSHIP)
- 綁定組播IP地址
- 接收群組消息
特殊處理機制
超時控制
- 接收超時結構體:
| struct timeval { |
| __kernel_time_t tv_sec; // 秒 |
| __kernel_suseconds_t tv_usec; // 微秒 |
| }; |
錯誤檢測
- 返回值檢測:
recvfrom
返回0表示空數據包EAGAIN
錯誤處理非阻塞狀態- 發送失敗重試機制
通信限制對比
特性 | 單播 | 廣播 | 組播 |
---|
地址范圍 | 具體IP | 255結尾地址 | 224-239網段 |
跨路由器 | 支持 | 不支持 | 支持 |
適用場景 | 精準傳輸 | 局域網通知 | 群組通信 |
資源消耗 | 低 | 高 | 中等 |
代碼結構示例
組播接收端
| // 加入組播組 |
| struct ip_mreqn mreq; |
| mreq.imr_multiaddr.s_addr = inet_addr("224.1.2.3"); |
| mreq.imr_address.s_addr = inet_addr("192.168.1.100"); |
| mreq.imr_ifindex = 0; |
| setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); |
廣播發送端
| // 啟用廣播權限 |
| int broadcast = 1; |
| setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); |

| # 心跳包核心要點 |
| |
| ## 基本概念 |
| - **定義**:用于維持長連接的活躍狀態,防止網絡設備斷開空閑連接 |
| - **核心目的**: |
| - 檢測客戶端存活狀態 |
| - 避免防火墻/NAT誤判連接失效 |
| |
| ## 實現機制 |
| ### 時間戳維護 |
| - **客戶端**:發送業務消息或心跳包時更新最后通信時間 |
| - **服務端**: |
| - 接收消息后更新時間戳 |
| - 維護客戶端列表(IP+Port+最后通信時間) |
| |
| ### 心跳包發送 |
| - **周期觸發**:客戶端每30秒發送空數據包 |
| - **信號機制**: |
| ```c |
| signal(SIGALRM, handler); // 注冊ALRM信號處理函數 |
| alarm(5); // 每5秒觸發信號 |
超時檢測
- 定時任務:服務端每秒檢查時間差
- 超時閾值:60秒無通信判定離線
- 清理邏輯:
| if(time(NULL) - tm > 4) { |
| 刪除客戶端記錄 |
| } |
關鍵函數
時間處理
- time():獲取1970年至今秒數
- localtime():轉換時間戳為tm結構體
- strftime():格式化時間輸出(如"%Y-%m-%d %H:%M:%S")
網絡通信
- recvfrom():接收UDP數據包
- sendto():發送心跳包或業務數據
數據結構
消息類型
enum type_t { CHAR, HEART }; // CHAR=業務消息,HEART=心跳包
消息結構體
| typedef struct msgbuf { |
| enum type_t type; // 消息類型 |
| char text[128]; // 消息內容 |
| } msgbuf_t; |
客戶端狀態記錄
| typedef struct timebuf { |
| unsigned int ip; // 客戶端IP |
| unsigned short port;// 端口號 |
| time_t tm; // 最后通信時間 |
| } timebuf_t; |
代碼結構
服務端邏輯
- 創建UDP套接字并綁定端口
- 啟動獨立線程檢測超時客戶端
- 接收消息后分類處理:
- CHAR類型:更新通信時間并處理業務
- HEART類型:僅更新時間戳
客戶端邏輯
- 創建UDP套接字連接服務端
- 設置定時器發送心跳包:
| handler() { |
| sendto(HEART包); |
| alarm(5); // 重置5秒定時 |
| } |
多線程處理
- 超時檢測線程:
| pthread_create(&thread, NULL, cli_delete, NULL); |
| pthread_detach(thread); // 分離線程 |
- 清理邏輯:
- for循環遍歷客戶端列表,刪除超時記錄、
