使用 UdpClient 實作多點廣播聊天室。所有客戶端加入同一多點廣播群組(預設 10.0.0.1:8080),透過 UDP 資料報收發訊息。無中央伺服器,每個節點同時是發送者與接收者。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
public class ChatForm : Form
{
private UdpClient _client;
private IPEndPoint _remoteEP;
private Thread _listenThread;
private const int PORT = 8080;
private const string MULTICAST_IP = "10.0.0.1";
private ListBox _lstMessages;
private TextBox _txtInput;
private Button _btnSend;
public ChatForm()
{
InitializeUI();
InitializeNetwork();
_listenThread = new Thread(ListenLoop) { IsBackground = true };
_listenThread.Start();
}
private void InitializeUI()
{
_lstMessages = new ListBox { Dock = DockStyle.Top, Height = 200 };
_txtInput = new TextBox { Dock = DockStyle.Bottom, Height = 30 };
_btnSend = new Button { Text = "發送", Dock = DockStyle.Bottom, Height = 35 };
_btnSend.Click += (s, e) => SendMessage();
Controls.AddRange(new Control[] { _lstMessages, _txtInput, _btnSend });
Text = "UDP 聊天室"; ClientSize = new Size(400, 400);
FormClosing += (s, e) => Cleanup();
}
private void InitializeNetwork()
{
_client = new UdpClient(PORT);
_remoteEP = new IPEndPoint(IPAddress.Parse(MULTICAST_IP), PORT);
_client.JoinMulticastGroup(IPAddress.Parse(MULTICAST_IP));
}
private void ListenLoop()
{
try
{
while (true)
{
IPEndPoint ep = null;
byte[] data = _client.Receive(ref ep);
string msg = Encoding.UTF8.GetString(data);
Invoke(() => _lstMessages.Items.Add($"[{ep.Address}] {msg}"));
}
}
catch (SocketException) { /* 正常關閉 */ }
}
private void SendMessage()
{
string text = _txtInput.Text.Trim();
if (string.IsNullOrEmpty(text)) return;
byte[] data = Encoding.UTF8.GetBytes(text);
_client.Send(data, data.Length, _remoteEP);
_txtInput.Clear();
}
private void Cleanup()
{
try { _client?.DropMulticastGroup(IPAddress.Parse(MULTICAST_IP)); } catch { }
try { _listenThread?.Abort(); } catch { }
_client?.Close();
}
}
| 技術 | 說明 |
|---|---|
| UdpClient | UDP 通訊封裝,支援發送/接收/多點廣播 |
| 多點廣播 | IP 範圍 224.0.0.0–239.255.255.255,單次發送到達群組所有成員 |
| JoinMulticastGroup | 加入群組接收資料,需指定本機介面 IP(多網卡環境) |
| 背景執行緒 | 接收迴圈阻塞於 Receive(),必須在獨立執行緒執行 |
| Control.Invoke | 跨執行緒更新 UI 必須封送回 UI 執行緒 |
JoinMulticastGroup(groupIP, localInterfaceIP) 指定介面CancellationToken 取代 Thread.Abort() 優雅關閉