.Net Core 使用UDP协议实现即时通讯

  • Post author:
  • Post category:其他


TCP与UDP的优缺点这里就不说明了。。。

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

namespace UDPTestByCore
{
    class Program
    {
        /// <summary>
        /// 用于UDP发送的网络服务类
        /// </summary>
        private static UdpClient udpcSend = null;

        static IPEndPoint localIpep = null;

        public static void Main(string[] args)
        {
            Console.Write("IP:");
            string ip = Console.ReadLine();
            Console.Write("Port:");
            int port = int.Parse(Console.ReadLine());
            localIpep = new IPEndPoint(IPAddress.Parse(ip), port); // 本机IP,指定的端口号

            udpcSend = new UdpClient(localIpep);

            StartReceive();

            // 实名发送
            string msg = null;
            while ((msg = Console.ReadLine()) != null)
            {
                if ("stop" == msg)
                {
                    StopReceive();
                    udpcSend.Close();
                }
                else
                {
                    //string[] arr = Console.ReadLine().Split(' ');
                    Thread thrSend = new Thread(SendMessage);
                    thrSend.Start(msg);
                }
            }
            Console.ReadKey();
        }

        /// <summary>
        /// 发送信息
        /// </summary>
        /// <param name="obj"></param>
        private static void SendMessage(object obj)
        {
            try
            {
                string message = obj.ToString();
                string[] array = message.Split(' ');
                IPAddress iPAddress = IPAddress.Parse(array[0]);
                int port = int.Parse(array[1]);
                byte[] sendbytes = Encoding.Unicode.GetBytes(array[2]);
                IPEndPoint remoteIpep = new IPEndPoint(iPAddress, port); // 发送到的IP地址和端口号
                udpcSend.Send(sendbytes, sendbytes.Length, remoteIpep);
            }
            catch { }
        }

        /// <summary>
        /// 开关:在监听UDP报文阶段为true,否则为false
        /// </summary>
        static bool IsUdpcRecvStart = false;
        /// <summary>
        /// 线程:不断监听UDP报文
        /// </summary>
        static Thread thrRecv;

        private static void StartReceive()
        {
            if (!IsUdpcRecvStart) // 未监听的情况,开始监听
            {
                thrRecv = new Thread(ReceiveMessage);
                thrRecv.Start();
                IsUdpcRecvStart = true;
                Console.WriteLine("UDP监听器已成功启动");
            }
        }

        private static void StopReceive()
        {
            if (IsUdpcRecvStart)
            {
                thrRecv.Abort(); // 必须先关闭这个线程,否则会异常
                IsUdpcRecvStart = false;
                Console.WriteLine("UDP监听器已成功关闭");
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="obj"></param>
        private static void ReceiveMessage(object obj)
        {
            while (IsUdpcRecvStart)
            {
                try
                {
                    byte[] bytRecv = udpcSend.Receive(ref localIpep);
                    string message = Encoding.Unicode.GetString(bytRecv, 0, bytRecv.Length);
                    Console.WriteLine(string.Format("{0}[{1}]", localIpep, message));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }
        }
    }
}

可以同一台电脑使用两个端口号测试。

发送消息格式为  接受端IP 接受端端口号 内容。(空格隔开)

具体可以根据需要修改。

这里只是简单的通讯,但实际使用中我们是不会知道接受端的IP和端口号的,我们可以通过以下方法实现。

1.即时通讯要有状态心跳包,我们可以通过客户端向服务的发送心跳信息时存储客户端对应的IP和端口(至于怎么获取请仔细看上面的代码。。。)自然这种数据存储在Redis等内存数据库中最好了。

2.使用上面代码修改为服务端,原理也比较简单,我们要知道服务端的IP 和端口号。创建一个新的Socket 用来获取状态数据并保存对应客户端的IP和端口号。

3.在客户端获取好友状态数据时获取对应的最新的IP和端口号(至于好友关系大家自己脑补,也比较简单。)。

4.有了IP和端口号还怕发不出消息吗?OK .

其实有人会有疑问:我的电脑是经过路由器的,没有固定IP 和端口号,其实这个可以研究一下网络通信相关的知识。

简单说一下

用户 要访问  百度

大家知道百度的服务器(站点)是有固定IP的,所以用户请求百度是很好理解的,但百度怎么讲返回数据发送给用户呢?因为用户并没有固定的IP。

原理是 举例

用户访问百度时 经过了两个路由器 分别是A 和B

用户在经过A路由器时 A路由器会分配给用户一个唯一的端口号 并携带这些信息去请求B路由器 B路由器同样会给它分配一个端口,接着访问到百度的服务器,服务器将结果数据原路返回,经过B 经过A 直到用户端。。。。。也就是说他们是通过对应的端口号来区分的。



版权声明:本文为u014518337原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。