hello

c#UDP发送接收消息

 

UDP作为一种简单的、面向数据报的无连接的协议,虽然提供的是不可靠的服务,但是从速度上、一对多传输方面比TCP有着很大的优势。本文主要讲解UDP信息的发送和接收。

Demo界面图如下:

首先打开程序exe文件开启“接收”的服务,然后再次启动程序,输入信息,即可发送信息了,效果图如下:

   

 

细心的人会发现,我在接受消息时,已经把接收到的每一个字符的ASCII码的十进制值给打印出来了,这是为了区别Encoding.Default和Encoding.Unicode编码方式的区别。

如下面的小例子:

用Encoding.Default方式进行编码

            string message = "hello";
            byte[] sendbytes = Encoding.Default.GetBytes(message);
            for (int i = 0; i < sendbytes.Length; i++)
            {
                ShwMsgForView.ShwMsgforView(listBox, string.Format("{0}", sendbytes[i].ToString()));
            }
            ShwMsgForView.ShwMsgforView(listBox, "发送消息:" + message);
            return;

输出的结果为:

用Encoding.Unicode方式进行编码

            string message = "hello";
            //byte[] sendbytes = Encoding.Default.GetBytes(message);
            byte[] sendbytes = Encoding.Unicode.GetBytes(message);
            for (int i = 0; i < sendbytes.Length; i++)
            {
                ShwMsgForView.ShwMsgforView(listBox, string.Format("{0}", sendbytes[i].ToString()));
            }
            ShwMsgForView.ShwMsgforView(listBox, "发送消息:" + message);
            return;
输出的结果为:


结果一目了然,如果使用Encoding.Unicode编码方式对字符串进行编码的话,会自动的在每一个字符后面加一个0,这是因为在字符串转换到字节数组的过程中,Encoding.Default 会将每个单字节字符,
如半角英文,转换成一个字节;而把每个双字节字符,如汉字,转换成2个字节。而 Encoding.Unicode 则会将它们都转换成两个字节。因为和我们进行数据通信的终端基本都会传输ASCII码值,而不会进行Unicode编码
所以,我采用的Default编码方式。

下面为系统代码:
        public Main()
        {
            InitializeComponent();
            systemLog = new BusinessLogicLayer.SystemLog();
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
            txtlocalIp.Text = ips[1].ToString();
            int port = 51888;
            txtlocalPort.Text = port.ToString();
            txtSndtoIP.Text = ips[1].ToString();
            txtSndtoPort.Text = port.ToString();
            chkbxAnonymous.Checked = true;
            btnStop.Enabled = false;
        }

这里我在获取本机IP地址时用的是ips[1].ToString(),发现很多都是用ips[0].ToString()。经过调试发现,ips[0].ToString()为IPV6的地址,而ips[1].ToString()才是IPV4的地址。如下图:

调试图

CMD查看ipconfig图

 

发送信息类代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Windows.Forms;

namespace BusinessLogicLayer
{
    public class SendMessage
    {
        private static UdpClient sendUdpClient;
        private static string sendIP;
        private static string sendToPort;
        private static ListBox listBox;
        private static SystemLog systemLog = new SystemLog();
        #region 发送消息
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="sendMsg"></param>
        /// <param name="sendIp"></param>
        /// <param name="sendPort"></param>
        public static void SendMsgStart(string sendMsg, string sendIp, string sendPort, ListBox listbox)
        {
            //给参数赋值
            sendIP = sendIp;
            sendToPort = sendPort;
            listBox = listbox;

            //选择发送模式
            //固定为匿名模式(套接字绑定的端口由系统自动分配)
            sendUdpClient = new UdpClient(0);
            //启动发送线程
            Thread threadSend = new Thread(SendMessages);
            threadSend.IsBackground = true;
            threadSend.Start(sendMsg);
            //显示状态
            ShwMsgForView.ShwMsgforView(listBox, "发送线程启动");
            //将数据存入数据库
            systemLog.SaveSystemLog("", "发送线程启动", "管理员");
        }

        private static void SendMessages(object obj)
        {
            string message = (string)obj;
            //byte[] sendbytes = Encoding.Unicode.GetBytes(message);
            //使用Default编码,如果使用Unicode编码的话,每个字符中间都会有个0,影响解码
            byte[] sendbytes = Encoding.Default.GetBytes(message);
            IPAddress remoteIp = IPAddress.Parse(sendIP);
            IPEndPoint remoteIPEndPoint = new IPEndPoint(remoteIp, int.Parse(sendToPort));
            sendUdpClient.Send(sendbytes, sendbytes.Length, remoteIPEndPoint);
            sendUdpClient.Close();
            ShwMsgForView.ShwMsgforView(listBox, "发送消息:" + message);
            systemLog.SaveSystemLog("", "发送消息,目标:" + remoteIPEndPoint + ",消息内容为:" + message + "", "管理员");
        }
        #endregion
    }
}

接受消息类代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Windows.Forms;

namespace BusinessLogicLayer
{

     public class ReceiveMessage
    {
         private static UdpClient receiveUdpClient;
         private static ListBox listBox;
         private static SystemLog systemLog = new SystemLog();
         #region 接受消息
         public static void ReceiveStart(string localip,string localPort,ListBox listbox)
         {
             listBox = listbox;
             //创建接受套接字
             IPAddress localIP = IPAddress.Parse(localip);
             IPEndPoint localIPEndPoint = new IPEndPoint(localIP, int.Parse(localPort));
             receiveUdpClient = new UdpClient(localIPEndPoint);
             //启动接受线程
             Thread threadReceive = new Thread(ReceiveMessages);
             threadReceive.IsBackground = true;
             threadReceive.Start();
             //显示状态
             ShwMsgForView.ShwMsgforView(listBox, "接受线程启动");
             //将数据存入数据库
             systemLog.SaveSystemLog("", "接受线程启动", "管理员");
         }

         private static void ReceiveMessages()
         {
             IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
             while (true)
             {
                 try
                 {
                     //关闭receiveUdpClient时此句会产生异常

                     byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIPEndPoint);
                     for (int i = 0; i < receiveBytes.Length; i++)
                     {
                         ShwMsgForView.ShwMsgforView(listBox, string.Format("{0}[{1}]", remoteIPEndPoint, receiveBytes[i].ToString()));
                     }
                     // string message = Encoding.Unicode.GetString(receiveBytes, 0, receiveBytes.Length);
                     string message = Encoding.ASCII.GetString(receiveBytes, 0, receiveBytes.Length);
                     //显示接受到的消息内容
                     ShwMsgForView.ShwMsgforView(listBox, string.Format("{0}[{1}]", remoteIPEndPoint, message));
                 }
                 catch   
                 {
                     break;
                 }
             }
         }

         public static void CloseReceiveUdpClient()
         {
             receiveUdpClient.Close();
             ShwMsgForView.ShwMsgforView(listBox, "接收线程停止");
             systemLog.SaveSystemLog("", "接收线程停止", "管理员");
         }
         #endregion
    }
}

显示消息类代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace BusinessLogicLayer
{
    public class ShwMsgForView
    {
        delegate void ShwMsgforViewCallBack(ListBox listbox, string text);
        public static void ShwMsgforView(ListBox listbox, string text)
        {
            if (listbox.InvokeRequired)
            {
                ShwMsgforViewCallBack shwMsgforViewCallBack = ShwMsgforView;
                listbox.Invoke(shwMsgforViewCallBack, new object[] { listbox, text });
            }
            else
            {
                listbox.Items.Add(text);
                listbox.SelectedIndex = listbox.Items.Count - 1;
                listbox.ClearSelected();
            }
        }
    }
}

至此UDP发送和接收消息搞定,下篇文章分享下使用TCP传输文件。

 

posted @ 2012-08-09 23:58  B追风少年  阅读(17854)  评论(0编辑  收藏  举报

hello too