zoukankan      html  css  js  c++  java
  • 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传输文件。

  • 相关阅读:
    前中后序建立树或者直接历遍
    Leetcode:面试题 04.03. 特定深度节点链表
    按层数层序历遍
    Solidity函数修饰符
    无线传感网定位技术
    无线传感器网络概述,传感器网络结构
    Solidity高级用法
    智能合约交互
    内存
    CPU的态
  • 原文地址:https://www.cnblogs.com/bianlan/p/2631101.html
Copyright © 2011-2022 走看看