C# UDP编程(通过类UdpClient实现收发)

jopen 9年前

1.程序说明

今天学了C#的UDP,实现了一个非常简单的UDP收发工具

C# UDP编程(通过类UdpClient实现收发)

这个工具的功能就是发送UDP报文和监听UDP报文。在左侧的文本框中输入文字,单击“发送数据”按钮发送UDP报文。如果这个时候点击了右边的“接收数据”按钮,右边的文本框会显示左边发送的数据。右侧的按钮,按一次开始监听,按第二次终止监听。

2.控件布局

程序的控件布局如下图

C# UDP编程(通过类UdpClient实现收发)

3.程序代码

程序的C#代码如下:

using System;  using System.Collections.Generic;  using System.ComponentModel;  using System.Data;  using System.Drawing;  using System.Linq;  using System.Text;  using System.Threading.Tasks;  using System.Windows.Forms;    //本段代码中需要新增加的命名空间  using System.Net.Sockets;  using System.Net;  using System.Threading;    namespace UDPTest  {      public partial class FormMain : Form      {          public FormMain()          {              InitializeComponent();          }            /// <summary>          /// 用于UDP发送的网络服务类          /// </summary>          private UdpClient udpcSend;          /// <summary>          /// 用于UDP接收的网络服务类          /// </summary>          private UdpClient udpcRecv;            /// <summary>          /// 按钮:发送数据          /// </summary>          /// <param name="sender"></param>          /// <param name="e"></param>          private void btnSend_Click(object sender, EventArgs e)          {              if (string.IsNullOrWhiteSpace(txtSendMssg.Text))              {                  MessageBox.Show("请先输入待发送内容");                  return;              }                // 匿名发送              //udpcSend = new UdpClient(0);             // 自动分配本地IPv4地址                // 实名发送              IPEndPoint localIpep = new IPEndPoint(                  IPAddress.Parse("127.0.0.1"), 12345); // 本机IP,指定的端口号              udpcSend = new UdpClient(localIpep);                Thread thrSend = new Thread(SendMessage);              thrSend.Start(txtSendMssg.Text);          }            /// <summary>          /// 发送信息          /// </summary>          /// <param name="obj"></param>          private void SendMessage(object obj)          {              string message = (string)obj;              byte[] sendbytes = Encoding.Unicode.GetBytes(message);                IPEndPoint remoteIpep = new IPEndPoint(                  IPAddress.Parse("127.0.0.1"), 8848); // 发送到的IP地址和端口号                udpcSend.Send(sendbytes, sendbytes.Length, remoteIpep);              udpcSend.Close();                ResetTextBox(txtSendMssg);          }            /// <summary>          /// 开关:在监听UDP报文阶段为true,否则为false          /// </summary>          bool IsUdpcRecvStart = false;          /// <summary>          /// 线程:不断监听UDP报文          /// </summary>          Thread thrRecv;            /// <summary>          /// 按钮:接收数据开关          /// </summary>          /// <param name="sender"></param>          /// <param name="e"></param>          private void btnRecv_Click(object sender, EventArgs e)          {              if (!IsUdpcRecvStart) // 未监听的情况,开始监听              {                  IPEndPoint localIpep = new IPEndPoint(                      IPAddress.Parse("127.0.0.1"), 8848); // 本机IP和监听端口号                    udpcRecv = new UdpClient(localIpep);                    thrRecv = new Thread(ReceiveMessage);                  thrRecv.Start();                    IsUdpcRecvStart = true;                  ShowMessage(txtRecvMssg, "UDP监听器已成功启动");              }              else                  // 正在监听的情况,终止监听              {                  thrRecv.Abort(); // 必须先关闭这个线程,否则会异常                  udpcRecv.Close();                    IsUdpcRecvStart = false;                  ShowMessage(txtRecvMssg, "UDP监听器已成功关闭");              }          }            /// <summary>          /// 接收数据          /// </summary>          /// <param name="obj"></param>          private void ReceiveMessage(object obj)          {              IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);              while (true)              {                  try                  {                      byte[] bytRecv = udpcRecv.Receive(ref remoteIpep);                      string message = Encoding.Unicode.GetString(                          bytRecv, 0, bytRecv.Length);                        ShowMessage(txtRecvMssg,                           string.Format("{0}[{1}]", remoteIpep, message));                  }                  catch (Exception ex)                  {                      ShowMessage(txtRecvMssg, ex.Message);                      break;                  }              }          }            // 向TextBox中添加文本          delegate void ShowMessageDelegate(TextBox txtbox, string message);          private void ShowMessage(TextBox txtbox, string message)          {              if (txtbox.InvokeRequired)              {                  ShowMessageDelegate showMessageDelegate = ShowMessage;                  txtbox.Invoke(showMessageDelegate, new object[] { txtbox, message });              }              else              {                  txtbox.Text += message + "\r\n";              }          }            // 清空指定TextBox中的文本          delegate void ResetTextBoxDelegate(TextBox txtbox);          private void ResetTextBox(TextBox txtbox)          {              if (txtbox.InvokeRequired)              {                  ResetTextBoxDelegate resetTextBoxDelegate = ResetTextBox;                  txtbox.Invoke(resetTextBoxDelegate, new object[] { txtbox });              }              else              {                  txtbox.Text = "";              }          }            /// <summary>          /// 关闭程序,强制退出          /// </summary>          /// <param name="sender"></param>          /// <param name="e"></param>          private void FormMain_FormClosing(object sender, FormClosingEventArgs e)          {              Environment.Exit(0);          }      }  }

4.其他

在关闭UdpClient(调用它的Close函数)前,一定要先关闭监听UDP的线程,否则会报错:“一个封锁操作被对 WSACancelBlockingCall 的调用中断”。

END


来自:http://my.oschina.net/Tsybius2014/blog/351974