UDP (User Datagram Protocol) 是無連線、不可靠的傳輸協定,但支援廣播,適合區域網路自動發現、簡訊廣播、遊戲大廳等場景。本文提供最精簡的 VC++ 發送端/接收端完整程式碼,展示 SO_BROADCAST 選項設定、sendto/recvfrom 使用方式。
// 初始化 Winsock
WSADATA wsdata; WSAStartup(0x0202, &wsdata);
// 本地綁定位址 (任意介面)
sockaddr_in local; local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0
local.sin_port = htons(5050);
// 廣播來源位址 (用於 recvfrom 取得發送者資訊)
sockaddr_in from; from.sin_family = AF_INET;
from.sin_addr.s_addr = INADDR_BROADCAST;
from.sin_port = htons(5050);
int fromlen = sizeof(sockaddr);
// 建立 UDP Socket
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
// 關鍵:啟用廣播屬性
BOOL optval = TRUE;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&optval, sizeof(optval));
// 綁定本地 Port
bind(s, (sockaddr*)&local, sizeof(local));
// 接收迴圈
char buf[256];
while (running) {
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);
}
Sleep(100); // 避免佔滿 CPU
}
closesocket(s); WSACleanup();
WSADATA wsdata; WSAStartup(0x0202, &wsdata);
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
BOOL optval = TRUE;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&optval, sizeof(optval));
sockaddr_in dest; dest.sin_family = AF_INET;
dest.sin_port = htons(5050);
dest.sin_addr.s_addr = inet_addr("255.255.255.255"); // 全網廣播
// 或 inet_addr("192.168.1.255") 針對特定子網
char msg[] = "Hello LAN Broadcast!";
while (running) {
sendto(s, msg, strlen(msg), 0, (sockaddr*)&dest, sizeof(dest));
Sleep(2000); // 每 2 秒廣播一次
}
closesocket(s); WSACleanup();
| 問題 | 原因 | 解決 |
|---|---|---|
| 接收端收不到 | 防火牆阻擋 UDP 5050 | 防火牆開放該 Port 或關閉防火牆測試 |
| 跨路由器收不到 | 路由器預設不轉發廣播 | 改用多播或特定子網廣播位址 |
| 發送端 sendto 失敗 | 未設定 SO_BROADCAST | 必須在 bind 前/後呼叫 setsockopt 啟用 |
| Win9x 執行錯誤 | Winsock 版本 | 使用 WSAStartup(MAKEWORD(1,1), ...) |
MSG_TYPE|SEQ|PAYLOAD,實現可靠廣播 (ACK/NAK)。WSAAsyncSelect 或 WSAEventSelect 非同步接收,避免阻塞主執行緒。DISCOVER,伺服器單播回應 OFFER (DHCP 類似機制)。UDP 廣播是區域網路輕量級通訊的基石,核心在於 SO_BROADCAST + sendto/recvfrom。本文提供最小可行程式碼,可直接整合至 MFC/Console 專案,作為聊天室大廳、裝置發現、遊戲同步等功能的起點。