區域網路內需向一組使用者同時發送資料(如視訊會議、即時廣播),逐一發送不僅效率低、易漏發,還浪費頻寬。**IP 多播** 正是為此而生:一份資料、一個目的地址、送達所有感興趣的接收者。本文從概念、位址、IGMP 協定到 VC++ 實作全面解析。
| 術語 | 說明 |
|---|---|
| 單播 | 一對一,傳統 TCP/UDP |
| 廣播 | 一對全網段,所有主機必須處理,無連線協定常用 |
| 多播 | 一對多,**僅有「加入群組」的主機接收**,節省頻寬與 CPU |
224.0.0.1 (全系統)、224.0.0.2 (全路由器)、224.0.0.5/6 (OSPF)、224.0.1.1 (NTP)
WSAData wsa; WSAStartup(MAKEWORD(2,2), &wsa);
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// 允許本地回環接收自己發送的多播 (除錯用)
char loop = 1; setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
// 設定 TTL (躍點數),區域網路通常 1~32
char ttl = 32; setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
sockaddr_in dest; dest.sin_family = AF_INET;
dest.sin_port = htons(5000);
dest.sin_addr.s_addr = inet_addr("239.255.1.1"); // 多播群組位址
char buf[1024];
while (cin.getline(buf, sizeof(buf))) {
sendto(s, buf, strlen(buf), 0, (sockaddr*)&dest, sizeof(dest));
}
sockaddr_in local; local.sin_family = AF_INET;
local.sin_port = htons(5000);
local.sin_addr.s_addr = INADDR_ANY;
bind(s, (sockaddr*)&local, sizeof(local));
// 構造 ip_mreq 結構:多播群組 + 本機介面
ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("239.255.1.1");
mreq.imr_interface.s_addr = INADDR_ANY; // 或指定具體 NIC IP
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq));
// 接收迴圈
sockaddr_in from; int fromlen = sizeof(from);
char buf[1024];
while (true) {
int n = recvfrom(s, buf, sizeof(buf), 0, (sockaddr*)&from, &fromlen);
if (n > 0) {
buf[n] = 0;
printf("[%s:%d] %s\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf);
}
}
| 現象 | 原因 | 對策 |
|---|---|---|
| 同機 Sender/Receiver 收不到 | 未設 IP_MULTICAST_LOOP 或防火牆阻擋 | 設 loop=1、加防火牆例外 |
| 跨交換機收不到 | 交換機未啟用 IGMP Snooping | 開啟 IGMP Snooping 或設定靜態多播轉發 |
| 資料亂序/重複 | UDP 無序、無可靠性 | 應用層加序號、去重、FEC/ARQ |
| TTL 太小不跨子網 | 預設 TTL=1 僅限本地鏈路 | 視拓撲設 TTL=32~128 |
IP 多播是「一份資料、精準送達」的網路藝術。掌握 D 類位址、IGMP 群組管理、Socket 選項 三大支柱,配合 VC++ Winsock 實作,即可打造高效能的區域網路廣播系統——視訊會議、即時股價推送、遊戲狀態同步,盡在掌握。下一步可探索 **SSM (Source-Specific Multicast, 232.0.0.0/8)** 與 **可靠多播協定 (PGM, RMT)**,進軍企業級應用。