ibcadmin 发表于 2012-12-21 17:52:38

UDP编程的具体实现-C#初识UDP(二)

紧接着上节课讲UDP,这节课讲解UDP编程的具体实现

UDP编程的具体实现
由于UDP进程在通信之前是不需要建立连接,消息接收方可能并不知道是谁给它发的消息,因此UDP编程分为两种模式:一种“实名发送”,即接收方可以由收到的消息得知发送方进程端口,另外一种则为“匿名发送”,即接收方并不知道发给它信息的远程进程究竟来自哪个端口。下面通过一个winform 程序来演示下UDP的编程:

实现代码:

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

namespace UDPClient
{
    public partial class frmUdp : Form
    {
      private UdpClient sendUdpClient;
      private UdpClient receiveUpdClient;
      public frmUdp()
      {
            InitializeComponent();
            IPAddress[] ips = Dns.GetHostAddresses("");
            tbxlocalip.Text = ips.ToString();
            int port = 51883;
            tbxlocalPort.Text = port.ToString();
            tbxSendtoIp.Text = ips.ToString();
            tbxSendtoport.Text = port.ToString();
      }

      // 接受消息
      private void btnReceive_Click(object sender, EventArgs e)
      {
            // 创建接收套接字
            IPAddress localIp = IPAddress.Parse(tbxlocalip.Text);
            IPEndPoint localIpEndPoint = new IPEndPoint(localIp, int.Parse(tbxlocalPort.Text));
            receiveUpdClient = new UdpClient(localIpEndPoint);


            Thread receiveThread = new Thread(ReceiveMessage);
            receiveThread.Start();
      }

      // 接收消息方法
      private void ReceiveMessage()
      {
            IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            {
                try
                {
                  // 关闭receiveUdpClient时此时会产生异常
                  byte[] receiveBytes = receiveUpdClient.Receive(ref remoteIpEndPoint);

                  string message = Encoding.Unicode.GetString(receiveBytes);

                  // 显示消息内容
                  ShowMessageforView(lstbxMessageView, string.Format("{0}[{1}]", remoteIpEndPoint, message));
                }
                catch
                {
                  break;
                }
            }
      }

      // 利用委托回调机制实现界面上消息内容显示
      delegate void ShowMessageforViewCallBack(ListBox listbox, string text);
      private void ShowMessageforView(ListBox listbox, string text)
      {
            if (listbox.InvokeRequired)
            {
                ShowMessageforViewCallBack showMessageforViewCallback = ShowMessageforView;
                listbox.Invoke(showMessageforViewCallback, new object[] { listbox, text });
            }
            else
            {
                lstbxMessageView.Items.Add(text);
                lstbxMessageView.SelectedIndex = lstbxMessageView.Items.Count - 1;
                lstbxMessageView.ClearSelected();
            }
      }
      private void btnSend_Click(object sender, EventArgs e)
      {
            if (tbxMessageSend.Text == string.Empty)
            {
                MessageBox.Show("发送内容不能为空","提示");
                return;
            }

            // 选择发送模式
            if (chkbxAnonymous.Checked == true)
            {
                // 匿名模式(套接字绑定的端口由系统随机分配)
                sendUdpClient = new UdpClient(0);
            }
            else
            {
                // 实名模式(套接字绑定到本地指定的端口)
                IPAddress localIp = IPAddress.Parse(tbxlocalip.Text);
                IPEndPoint localIpEndPoint = new IPEndPoint(localIp, int.Parse(tbxlocalPort.Text));
                sendUdpClient = new UdpClient(localIpEndPoint);
            }

            Thread sendThread = new Thread(SendMessage);
            sendThread.Start(tbxMessageSend.Text);
      }

      // 发送消息方法
      private void SendMessage(object obj)
      {
            string message = (string)obj;
            byte[] sendbytes = Encoding.Unicode.GetBytes(message);
            IPAddress remoteIp = IPAddress.Parse(tbxSendtoIp.Text);
            IPEndPoint remoteIpEndPoint = new IPEndPoint(remoteIp, int.Parse(tbxSendtoport.Text));
            sendUdpClient.Send(sendbytes, sendbytes.Length, remoteIpEndPoint);
         
            sendUdpClient.Close();
         
            // 清空发送消息框
            ResetMessageText(tbxMessageSend);
      }

      // 采用了回调机制
      // 使用委托实现跨线程界面的操作方式
      delegate void ResetMessageCallback(TextBox textbox);
      private void ResetMessageText(TextBox textbox)
      {
            // Control.InvokeRequired属性代表
            // 如果空间的处理与调用线程在不同线程上创建的,则为true,否则为false
            if (textbox.InvokeRequired)
            {
                ResetMessageCallback resetMessagecallback = ResetMessageText;
                textbox.Invoke(resetMessagecallback, new object[] { textbox });
            }
            else
            {
                textbox.Clear();
                textbox.Focus();
            }
      }

      // 停止接收
      private void btnStop_Click(object sender, EventArgs e)
      {
            receiveUpdClient.Close();
      }

      // 清空接受消息框
      private void btnClear_Click(object sender, EventArgs e)
      {
            this.lstbxMessageView.Items.Clear();
      }
    }
}



chao2332601 发表于 2013-6-16 03:28:07

谢谢分享!!!
页: [1]
查看完整版本: UDP编程的具体实现-C#初识UDP(二)