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傳輸文件。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM