首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 使用 UdpClient 實作簡易聊天程式(含多點廣播)

     編輯:關於C#

UdpClient 類別提供 UDP 協定通訊封裝,優點是簡單易用、支援廣播與多點傳送;缺點是無連線、不保證送達、不保證順序,應用層需自行處理丟包與亂序。本文示範以多點廣播實作區域網路聊天室。

UDP 廣播與多點傳送基礎

  • 有限廣播:255.255.255.255,僅限本地網段,路由器不轉發。
  • 直接廣播:如 192.168.255.255,目標特定網路。
  • 多點傳送:224.0.0.2 ~ 239.255.255.255,僅加入群組的主機接收,適合跨子網或特定群組通訊。

UdpClient 可發送多點廣播,但無法接收多點廣播(需用 Socket 綁定 IP_ADD_MEMBERSHIP 選項)。本範例為簡化示範,採用單一 UdpClient 同時收發至同一多點群組位址。

完整 WinForms 聊天室程式碼

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;

namespace WinUDPChat
{
    public class FormChat : Form
    {
        private static UdpClient _client;
        private const int ListenerPort = 8080;
        private const int SenderPort = 8080;
        private static readonly IPAddress GroupAddress = IPAddress.Parse("10.0.0.1"); // 多點群組位址
        private Thread _listenThread;
        private ListBox _listBoxMsg;
        private TextBox _textBoxMsg;
        private Button _btnSend;

        public FormChat()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            _listBoxMsg = new ListBox { Location = new Point(21, 22), Size = new Size(248, 136) };
            _textBoxMsg = new TextBox { Location = new Point(80, 197), Size = new Size(200, 20) };
            _btnSend = new Button { Text = "發送", Location = new Point(96, 234) };
            _btnSend.Click += BtnSend_Click;

            Controls.AddRange(new Control[] { _listBoxMsg, _textBoxMsg, _btnSend });
            Text = "UDP 聊天室";
            ClientSize = new Size(292, 273);
            Load += FormChat_Load;
            FormClosed += FormChat_Closed;
        }

        private void FormChat_Load(object sender, EventArgs e)
        {
            _client = new UdpClient(ListenerPort);
            _client.JoinMulticastGroup(GroupAddress, 100); // TTL=100

            _listenThread = new Thread(Listener);
            _listenThread.IsBackground = true;
            _listenThread.Start();
        }

        private void Listener()
        {
            IPEndPoint remoteEP = null;
            var encoding = Encoding.UTF8;
            try
            {
                while (true)
                {
                    byte[] data = _client.Receive(ref remoteEP);
                    string msg = encoding.GetString(data);
                    // 必須在 UI 執行緒更新控制項
                    Invoke((Action)(() => _listBoxMsg.Items.Add(msg)));
                }
            }
            catch (SocketException)
            {
                // Socket 關閉時會拋出,正常結束
            }
        }

        private void BtnSend_Click(object sender, EventArgs e)
        {
            string msg = _textBoxMsg.Text;
            if (string.IsNullOrEmpty(msg)) return;

            byte[] buffer = Encoding.UTF8.GetBytes(msg);
            IPEndPoint remoteEP = new IPEndPoint(GroupAddress, SenderPort);
            _client.Send(buffer, buffer.Length, remoteEP);
            _textBoxMsg.Clear();
        }

        private void FormChat_Closed(object sender, FormClosedEventArgs e)
        {
            try
            {
                _client?.DropMulticastGroup(GroupAddress);
                _listenThread?.Abort();
                _client?.Close();
            }
            catch { }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new FormChat());
        }
    }
}

關鍵點補充

  • 編碼:建議統一使用 UTF-8,避免中文亂碼。
  • 執行緒安全:接收迴圈在背景執行緒,更新 UI 必須用 Control.Invoke。
  • 資源釋放:關閉時呼叫 DropMulticastGroup、Close,並中止接收執行緒。
  • 防火牆:需開放 UDP 8080 埠(或自訂埠)的輸入/輸出規則。
  • 擴充性:實務上建議加入使用者名稱、訊息協定(JSON/Protobuf)、心跳偵測、重送機制等。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved