
窗体1using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Windows.Forms; namespace UdpServerDemo { public partial class Form1 : Form { private Socket udpServerSocket; private Thread listenThread; private bool isServerRunning false; public Form1() { InitializeComponent(); } // 启动UDP服务按钮1 private void btnStart_Click(object sender, EventArgs e) { if (!int.TryParse(txtPort.Text, out int port) || port 1 || port 65535) { MessageBox.Show(请输入合法端口); return; } try { // 创建UDP Socket udpServerSocket new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // 绑定本机所有网卡指定端口 IPEndPoint endPoint new IPEndPoint(IPAddress.Any, port); udpServerSocket.Bind(endPoint); isServerRunning true; // 新开线程循环接收数据防止界面卡死 listenThread new Thread(ReceiveLoop); listenThread.IsBackground true; listenThread.Start(); AppendLog($UDP服务已启动监听端口{port}); btnStart.Enabled false; btnStop.Enabled true; } catch (Exception ex) { AppendLog($启动失败{ex.Message}); } } // 循环接收客户端数据 private void ReceiveLoop() { byte[] buffer new byte[1024 * 10]; while (isServerRunning) { try { // 存储客户端地址 IPEndPoint clientEp new IPEndPoint(IPAddress.Any, 0); EndPoint remoteEp clientEp; // 阻塞等待接收数据 int recvLen udpServerSocket.ReceiveFrom(buffer, ref remoteEp); clientEp (IPEndPoint)remoteEp; // 解析收到的字符串 string recvStr Encoding.UTF8.GetString(buffer, 0, recvLen); string clientInfo ${clientEp.Address}:{clientEp.Port}; // 界面打印日志 Invoke(new Action(() { AppendLog($[{clientInfo}] 收到{recvStr}); })); // 给客户端回复消息 string response $服务端已收到你的消息{recvStr}; byte[] sendBuf Encoding.UTF8.GetBytes(response); udpServerSocket.SendTo(sendBuf, sendBuf.Length, SocketFlags.None, clientEp); Invoke(new Action(() { AppendLog($[{clientInfo}] 已回复{response}); })); } catch (SocketException) { // 服务关闭时抛出异常正常退出循环 } catch (Exception ex) { Invoke(new Action(() { AppendLog($接收异常{ex.Message}); })); } } } // 停止服务按钮 private void btnStop_Click(object sender, EventArgs e) { isServerRunning false; udpServerSocket?.Close(); listenThread?.Abort(); AppendLog(UDP服务已停止); btnStart.Enabled true; btnStop.Enabled false; } // 追加日志到文本框 private void AppendLog(string msg) { txtLog.AppendText(${DateTime.Now:HH:mm:ss} {msg}\r\n); // 自动滚动到最后一行 txtLog.SelectionStart txtLog.TextLength; txtLog.ScrollToCaret(); } // 窗口关闭时释放资源 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (isServerRunning) { udpServerSocket?.Close(); listenThread?.Abort(); } } private void button1_Click(object sender, EventArgs e) { //实例化客户端窗口 Form2 clientForm new Form2(); clientForm.Show(); } } }窗体2using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Windows.Forms; namespace UdpServerDemo { public partial class Form2 : Form { // 单Socket同时负责发送、接收 private Socket udpSocket; private Thread recvThread; private bool isRecving false; public Form2() { InitializeComponent(); // 创建UDP套接字并提前绑定随机本地端口收发共用此端口 udpSocket new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint localBindEp new IPEndPoint(IPAddress.Any, 0); udpSocket.Bind(localBindEp); // 初始关闭按钮不可点击 btnStopRecv.Enabled false; } // 开启后台持续接收线程 private void btnStartRecv_Click(object sender, EventArgs e) { if (isRecving) { AppendLog(后台接收已开启无需重复启动); return; } isRecving true; recvThread new Thread(ClientReceiveLoop); recvThread.IsBackground true; recvThread.Start(); AppendLog(✅ 客户端后台接收线程已启动); btnStartRecv.Enabled false; btnStopRecv.Enabled true; } // 后台循环接收服务端下发的数据 private void ClientReceiveLoop() { byte[] buffer new byte[1024 * 10]; while (isRecving) { try { EndPoint remoteEp new IPEndPoint(IPAddress.Any, 0); // 阻塞等待服务端消息 int recvLen udpSocket.ReceiveFrom(buffer, ref remoteEp); IPEndPoint serverEp (IPEndPoint)remoteEp; string msg Encoding.UTF8.GetString(buffer, 0, recvLen); Invoke(new Action(() { if (!this.IsDisposed) { AppendLog($[来自 {serverEp.Address}:{serverEp.Port}] 收到{msg}); } })); } catch (SocketException) { // 仅停止接收时跳出循环 if (!isRecving) break; } catch (Exception ex) { Invoke(new Action(() { if (!this.IsDisposed) { AppendLog($接收异常{ex.Message}); } })); } } } // 发送消息到服务端 private void btnSend_Click(object sender, EventArgs e) { // 1. 校验IP string ipStr txtServerIP.Text.Trim(); if (!IPAddress.TryParse(ipStr, out IPAddress serverIp)) { AppendLog(❌ IP地址格式错误); return; } // 2. 校验端口 string portStr txtServerPort.Text.Trim(); if (!int.TryParse(portStr, out int port) || port 1 || port 65535) { AppendLog(❌ 端口必须是1~65535数字); return; } // 3. 校验发送内容 string sendContent txtSendMsg.Text.Trim(); if (string.IsNullOrEmpty(sendContent)) { AppendLog(❌ 发送内容不能为空); return; } IPEndPoint targetEp new IPEndPoint(serverIp, port); byte[] sendBuf Encoding.UTF8.GetBytes(sendContent); try { // 使用共用Socket发送 udpSocket.SendTo(sendBuf, sendBuf.Length, SocketFlags.None, targetEp); AppendLog($→ 发送至 {serverIp}:{port} 内容{sendContent}); // 发送成功清空输入框并聚焦 txtSendMsg.Clear(); txtSendMsg.Focus(); } catch (Exception ex) { AppendLog($❌ 发送失败{ex.Message}检查服务端是否启动/防火墙拦截); } } // 日志追加工具方法 private void AppendLog(string info) { txtLog.AppendText(${DateTime.Now:HH:mm:ss} {info}\r\n); txtLog.SelectionStart txtLog.TextLength; txtLog.ScrollToCaret(); } // 关闭后台接收 private void btnStopRecv_Click(object sender, EventArgs e) { if (!isRecving) { AppendLog(当前未开启接收无需关闭); return; } // 标记停止循环 isRecving false; // 等待线程安全结束 recvThread?.Join(100); AppendLog(✅ 客户端后台接收已关闭); btnStartRecv.Enabled true; btnStopRecv.Enabled false; } // 窗口关闭释放资源 private void Form2_FormClosing(object sender, FormClosingEventArgs e) { // 先停止接收线程 if (isRecving) { isRecving false; recvThread?.Join(100); } // 程序退出再关闭套接字 udpSocket?.Close(); } } }