首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

區域網路 IP 多播通訊實作完整指南

     編輯:VC 教學

多播概念與優勢

  • 點對點:一對一,傳統通訊模式。
  • 廣播:一對全網段,所有主機皆需處理,資源浪費。
  • 多播:一對多(群組),僅有興趣的接收者加入群組才會收到資料,高效節頻。

應用場景:視訊會議、即時串流、股票行情推播、分散式系統狀態同步。

技術基礎

協定支援

Win32 平台僅 IP/ATM 協定支援多播。本文聚焦 TCP/IP 架構下的 IP 多播。

D 類位址

  • 範圍:224.0.0.0 ~ 239.255.255.255(註:原文 244 為筆誤)
  • 28 位群組識別碼,理論支援 2.6 億群組。
  • 永久位址(保留):224.0.0.1 全系統、224.0.0.2 所有路由器等。
  • 暫時位址:應用動態建立/釋放。

IGMP 協定

主機透過 IGMP(網際網路群組管理協定)向多播路由器報告群組加入/離開。路由器構建生成樹轉發封包。

Winsock 2 實作步驟

接收端

  1. 建立 SOCK_DGRAM Socket,旗標 WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF | WSA_FLAG_OVERLAPPED。
  2. bind 至本地埠口(如 5150)。
  3. 呼叫 WSAJoinLeaf 加入多播群組(旗標 JL_RECEIVER_ONLY 或 JL_BOTH)。
  4. recvfrom 迴圈接收資料。

發送端

  1. 建立同樣旗標的 Socket。
  2. WSAJoinLeaf 加入群組(旗標 JL_SENDER_ONLY 或 JL_BOTH)。
  3. sendto 發送資料至多播位址:埠口。

完整程式碼

Receiver.c

#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;
}

Sender.c

#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;
}

測試部署

  1. 編譯產生 Sender.exe、Receiver.exe。
  2. 發送端執行 Sender.exe。
  3. 多台接收端執行 Receiver.exe。
  4. 發送端輸入文字,所有接收端即時顯示。

Winsock 1 相容性說明

舊版需用 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 旗標、綁定埠口、加入群組三步驟。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved