c#如何使用UDP进行聊天通信

 更新时间:2023年06月16日 14:43:54   作者:故里2130  
这篇文章主要介绍了c#如何使用UDP进行聊天通信问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

c#使用UDP进行聊天通信

UDP和TCP都是网络通信中不可缺少的部分,两者在不同的环境中,应用的场景不一样,UDP在网络不好的情况下,传输会丢包,也就是会丢数据,而TCP不会这样,所以重要的数据使用TCP传输,但是TCP对网络的资源消耗非常的大,例如视频,音频等大量的数据,这个时候就选择UDP,因为UDP占用网络资源比较低,就算丢一帧二帧的图像的数据,也不会有影响的。

UDP只管发送,不管你有没有接收到信息,比较主动,同理,也会一直接收,只要在线,就能接受对方的信息。UDP比TCP的使用更加的简单。

UDP通信可以分为使用UDP和UdpClient。UdpClient是Socket的一种封装。其实UDP通信没有绝对的服务端和客户端分别,因为都是连接上,就可以发送和接收。

使用UDP方式,需要注意发送消息的IP地址和端口与接收消息的IP地址和端口。

服务端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //udp 服务端
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001));//绑定端口号和IP
            Console.WriteLine("服务端已经开启");
            Thread t = new Thread(()=>ReciveMsg(server));//开启接收消息线程
            t.Start();
            Thread t2 = new Thread(()=>sendMsg(server));//开启发送消息线程
            t2.Start();
        }
        static void sendMsg(Socket server)
        {
            EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000);    //向指定的IP和端口发送消息
            while (true)
            {
                string msg = Console.ReadLine();
                server.SendTo(Encoding.UTF8.GetBytes(msg), point);
            }
        }
        static void ReciveMsg(Socket server)
        {
            while (true)
            {
                //EndPoint point = new IPEndPoint(IPAddress.Any, 0);                   //向所有的IP和端口接收消息
                EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000);   //向指定的IP和端口接收消息
                byte[] buffer = new byte[1024];
                int length = server.ReceiveFrom(buffer, ref point);//接收数据报
                string message = Encoding.UTF8.GetString(buffer, 0, length);
                Console.WriteLine("收到了消息:" + message);
            }
        }
    }
}

客户端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            client.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000));
            Thread t = new Thread(() => sendMsg(client));
            t.Start();
            Thread t2 = new Thread(() => ReciveMsg(client));
            t2.Start();
            Console.WriteLine("客户端已经开启");
        }
        static void sendMsg(Socket client)
        {
            EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001);    //向指定的IP和端口发送消息
            while (true)
            {
                string msg = Console.ReadLine();
                client.SendTo(Encoding.UTF8.GetBytes(msg), point);
            }
        }
        static void ReciveMsg(Socket client)
        {
            while (true)
            {
                //EndPoint point = new IPEndPoint(IPAddress.Any, 0);                        //向所有的IP和端口接收消息
                EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001);        //向指定的IP和端口接收消息
                byte[] buffer = new byte[1024];
                int length = client.ReceiveFrom(buffer, ref point);//接收数据报
                string message = Encoding.UTF8.GetString(buffer, 0, length);
                Console.WriteLine("收到了消息:" + message);
            }
        }
    }
}

效果预览

使用UdpClient方式,需要注意发送消息的IP地址和端口与接收消息的IP地址和端口

服务端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建udpclient 绑定ip跟端口号
            UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090));
            Console.WriteLine("UdpClient服务端已经开启");
            Thread t = new Thread(() => ReciveMsg(udpClient));//开启接收消息线程
            t.Start();
            Thread t2 = new Thread(() => sendMsg(udpClient));//开启发送消息线程
            t2.Start();
        }
        static void sendMsg(UdpClient udpClient)
        {
            while (true)
            {
                string message = Console.ReadLine();
                byte[] data = Encoding.UTF8.GetBytes(message);
                udpClient.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8091));   //发送到指定的IP地址和端口信息
            }
        }
        static void ReciveMsg(UdpClient udpClient)
        {
            while (true)
            {
                //接收数据
                //IPEndPoint point = new IPEndPoint(IPAddress.Any, 0);                     //接收所有的IP地址和端口信息
                IPEndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8091);     //接收指定的IP地址和端口信息
                byte[] data = udpClient.Receive(ref point);// 
                string message = Encoding.UTF8.GetString(data);
                Console.WriteLine("收到了消息:" + message);
            }
        }
    }
}

客户端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建udpclient对象
            UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8091));
            Console.WriteLine("UdpClient客户端已经开启");
            Thread t = new Thread(() => sendMsg(client));
            t.Start();
            Thread t2 = new Thread(() => ReciveMsg(client));
            t2.Start();
        }
        static void sendMsg(UdpClient client)
        {
            while (true)
            {
                string message = Console.ReadLine();
                byte[] data = Encoding.UTF8.GetBytes(message);
                client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090));
            }
        }
        static void ReciveMsg(UdpClient udpClient)
        {
            while (true)
            {
                //接收数据
                //IPEndPoint point = new IPEndPoint(IPAddress.Any, 0);                      //接收所有的IP地址和端口信息
                IPEndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090);      //接收指定的IP地址和端口信息
                byte[] data = udpClient.Receive(ref point); 
                string message = Encoding.UTF8.GetString(data);
                Console.WriteLine("收到了消息:" + message);
            }
        }
    }
}

效果预览

从以上的案例来看,UDP和UdpClient的区别基本上都是一样的,一个使用了Socket 类,一个使用了UdpClient类,然后都是绑定对应的IP地址和端口,然后就是分别调用Socket类的方法,进行发送消息和接收消息,调用UdpClient类的方法,进行发送消息和接收信息。

其实在新建类的时候,可以不用先进行连接,可以把IP地址和端口,以及消息一次性发出去。

拓展

单播,广播,多播三者的区别

单播

用于两个主机之间的端对端通信,指定了固定的IP地址和端口,就是一对一的对话,其他人听不到你们说的话,类似私聊。

代码:就是上面的代码,指定了固定的IP地址和端口号,发送和接收都互相对应。

广播

用于一个主机对整个局域网上所有主机上的数据通信,就是一个人大声说话,所有的人都能听到,类似群聊。

代码:修改成下面2句即可,发送端和接收端都要修改。

UDP服务端

 server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);    //Broadcast开启广播
 EndPoint point = new IPEndPoint(IPAddress.Broadcast, 4567);    //开启广播,端口是4567

UDP客户端

 EndPoint iep = new IPEndPoint(IPAddress.Any, 4567);      //任意ip,端口就是服务端的4567
 EndPoint point = new IPEndPoint(IPAddress.Any, 4567);        //广播,端口是4567

UdpClient服务端

            UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
            IPEndPoint point = new IPEndPoint(IPAddress.Broadcast, 4567);    //开启广播,端口是4567

UdpClient客户端

 

            UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 4567));
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);

多播

介于单播和广播之间,也叫组播,从名字上面就能知道,建立一个组,然后向组内的人员发送消息,就类似,微信临时拉一个群,指定群内的人,向群内通知信息。

代码:修改成下面2句即可,发送端和接收端都要修改。

加入多播

                udpClient.JoinMulticastGroup(IPAddress.Parse("224.0.0.0"));//将 UdpClient 添加到多播组;IPAddress.Parse将IP地址字符串转换为IPAddress 实例
                IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("224.0.0.0"), 7788); //将网络终结点表示为 IP 地址和端口号  7788是目的端口

退出多播

udpClient.DropMulticastGroup(IPAddress.Parse("224.0.0.0"));//将 UdpClient 从多播组中移除;IPAddress.Parse将IP地址字符串转换为IPAddress 实例
                IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("224.0.0.0"), 7788); //将网络终结点表示为 IP 地址和端口号  7788是目的端口

带界面操作

代码 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;//在其他线程中可以调用主窗体控件
        }
        UdpClient udpClient;
        UdpClient client;
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread js = new Thread(() =>
            {
                client = new UdpClient(new IPEndPoint(IPAddress.Any, 4567));
                IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Any, 0);
                while (true)
                {
                    try
                    {
                        if (client.Available <= 0) continue;
                        if (client.Client == null) return;
                        byte[] bytes = client.Receive(ref iPEndPoint);
                        string str = Encoding.Default.GetString(bytes);
                        //Invoke(new Action(() => textBox2.Text = str));
                        textBox2.Text = str;
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                    Thread.Sleep(1000);
                }
            });
            js.Start();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
            IPEndPoint point = new IPEndPoint(IPAddress.Broadcast, 4567);    //开启广播,端口是4567
            if (textBox1.Text != null)
            {
                Byte[] sendBytes = Encoding.Default.GetBytes(textBox1.Text);
                udpClient.Send(sendBytes, sendBytes.Length, point);
            }
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            udpClient.Dispose();
            udpClient.Close();
            client.Dispose();
            client.Close();
        }
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C#基础知识之new关键字介绍

    C#基础知识之new关键字介绍

    在 C# 中,new 关键字可用作运算符、修饰符或约束,本文主要介绍这三种用法。
    2016-04-04
  • C#中this的用法集锦

    C#中this的用法集锦

    本文给大家汇总介绍了C#中的几种this用法,相信大家应该有用过,但你用过几种?以下是个人总结的this几种用法,欢迎大家拍砖,废话少说,直接列出用法及相关代码。
    2015-06-06
  • c#互斥锁Mutex类用法介绍

    c#互斥锁Mutex类用法介绍

    本文详细讲解了c#互斥锁Mutex类的用法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-02-02
  • C# WinForm程序完全退出的问题解决

    C# WinForm程序完全退出的问题解决

    C# WinForm程序完全退出的问题解决,需要的朋友可以参考一下
    2013-05-05
  • C# DataGridView添加新行的2个方法

    C# DataGridView添加新行的2个方法

    DataGridView控件在实际应用中非常实用,特别需要表格显示数据时。
    2013-03-03
  • C#实现winform中RichTextBox在指定光标位置插入图片的方法

    C#实现winform中RichTextBox在指定光标位置插入图片的方法

    这篇文章主要介绍了C#实现winform中RichTextBox在指定光标位置插入图片的方法,涉及RichTextBox控件及剪切板的相关操作技巧,非常简单实用,需要的朋友可以参考下
    2016-06-06
  • C#方法中参数ref和out详解

    C#方法中参数ref和out详解

    这篇文章主要为大家详细介绍了C#方法中参数ref和out的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • C# 制作PictureBox圆形头像框并从数据库中读取头像

    C# 制作PictureBox圆形头像框并从数据库中读取头像

    C#提供的PictureBox控键默认情况下是方形的非常大的影响美观,怎么解决这一问题呢?下面小编给大家带来了C# 制作PictureBox圆形头像框并从数据库中读取头像的操作代码,感兴趣的朋友一起学习下吧
    2021-08-08
  • C#控件命名规范汇总(超详细)

    C#控件命名规范汇总(超详细)

    本篇文章是对C#控件命名规范进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Unity3D实现飞机大战游戏(2)

    Unity3D实现飞机大战游戏(2)

    这篇文章主要为大家详细介绍了Unity3D实现飞机大战游戏的第二部分,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06

最新评论