應用場景:視訊會議、即時串流、股票行情推播、分散式系統狀態同步。
Win32 平台僅 IP/ATM 協定支援多播。本文聚焦 TCP/IP 架構下的 IP 多播。
224.0.0.0 ~ 239.255.255.255(註:原文 244 為筆誤)224.0.0.1 全系統、224.0.0.2 所有路由器等。主機透過 IGMP(網際網路群組管理協定)向多播路由器報告群組加入/離開。路由器構建生成樹轉發封包。
SOCK_DGRAM Socket,旗標 WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF | WSA_FLAG_OVERLAPPED。bind 至本地埠口(如 5150)。WSAJoinLeaf 加入多播群組(旗標 JL_RECEIVER_ONLY 或 JL_BOTH)。recvfrom 迴圈接收資料。WSAJoinLeaf 加入群組(旗標 JL_SENDER_ONLY 或 JL_BOTH)。sendto 發送資料至多播位址:埠口。#include
#include
#include
#define MCASTADDR "233.0.0.1"
#define MCASTPORT 5150
#define BUFSIZE 1024
int main() {
WSADATA wsd;
struct sockaddr_in local, remote, from;
SOCKET sock, sockM;
char recvbuf[BUFSIZE];
int len = sizeof(struct sockaddr_in), ret;
WSAStartup(MAKEWORD(2,2), &wsd);
sock = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0,
WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF | WSA_FLAG_OVERLAPPED);
local.sin_family = AF_INET;
local.sin_port = htons(MCASTPORT);
local.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr*)&local, sizeof(local));
remote.sin_family = AF_INET;
remote.sin_port = htons(MCASTPORT);
remote.sin_addr.s_addr = inet_addr(MCASTADDR);
sockM = WSAJoinLeaf(sock, (struct sockaddr*)&remote, sizeof(remote), NULL, NULL, NULL, NULL, JL_BOTH);
while (1) {
ret = recvfrom(sock, recvbuf, BUFSIZE, 0, (struct sockaddr*)&from, &len);
if (ret == SOCKET_ERROR) break;
recvbuf[ret] = '\0';
if (strcmp(recvbuf, "QUIT") == 0) break;
printf("RECV: '%s' FROM <%s>\n", recvbuf, inet_ntoa(from.sin_addr));
}
closesocket(sockM); closesocket(sock); WSACleanup();
return 0;
}
#include
#include
#include
#define MCASTADDR "233.0.0.1"
#define MCASTPORT 5150
#define BUFSIZE 1024
int main() {
WSADATA wsd;
struct sockaddr_in remote;
SOCKET sock, sockM;
char sendbuf[BUFSIZE];
int len = sizeof(struct sockaddr_in);
WSAStartup(MAKEWORD(2,2), &wsd);
sock = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0,
WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF | WSA_FLAG_OVERLAPPED);
remote.sin_family = AF_INET;
remote.sin_port = htons(MCASTPORT);
remote.sin_addr.s_addr = inet_addr(MCASTADDR);
sockM = WSAJoinLeaf(sock, (struct sockaddr*)&remote, sizeof(remote), NULL, NULL, NULL, NULL, JL_BOTH);
while (1) {
printf("SEND: "); scanf("%s", sendbuf);
sendto(sockM, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&remote, len);
if (strcmp(sendbuf, "QUIT") == 0) break;
Sleep(500);
}
closesocket(sockM); closesocket(sock); WSACleanup();
return 0;
}
Sender.exe、Receiver.exe。Sender.exe。Receiver.exe。舊版需用 setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast)) 加入群組,結構 ip_mreq 指定多播位址與介面。Winsock 2 的 WSAJoinLeaf 統一介面、協定無關,為現代首選。
IP 多播透過 D 類位址與 IGMP 實現高效一對多通訊。Winsock 2 提供 WSAJoinLeaf 簡化群組管理,搭配 UDP (SOCK_DGRAM) 即可快速建立多播應用。關鍵在於正確設定 Socket 旗標、綁定埠口、加入群組三步驟。