Socket编程-UDP实现发送组播信息

在System.net.Sockets名称空间中,UdpClient类简化了UDP套接字编程。UDP协议是无连接的协议,因此,UDP协议只有UdpClient类,而没有TcpListener类和TcpClient类。UdpClient类提供了发送和接受无连接的UDP数据报的方便方法。其建立默认远程主机的方式有两种:一是使用远程主机名和端口号作为参数创建UdpClient类的实例;另一种是先创建不带参数的UdpClient类的实例,然后调用Connet方法指定默认远程主机。

可以通过调用UdpClient对象的Send方法直接将数据发送到远程主机,该方法返回数据的长度可用于检查数据是否已被正确发送。UdpClient对象的Receive方法能够在指定的本地IP地址和端口上接收数据,该方法带一个引用类型的IPEndPoint实例,并将接收到的数据作为byte数组返回

UDP协议的重要用途是可以通过广播和组播实现一对多的通信。所谓广播,就是指同时向网络中的所有计算机发送消息,而这些计算机都可以接收到消息。组播也叫多路广播,是将消息从一台计算机发送到网络中指定的若干台计算机上,即发送到哪些加入指定组播组的计算机上,组播组是开放的,每台计算机都可以通过程序随时加入到组播组中,也可以随时退出。

组播地址是224.0.0.0到239.255.255.255的D类IP地址。使用组播时,应注意的是TTL值的设置,TTL值是允许路由器转发的最大数目。当达到这个最大值时,数据包就会被丢弃。如果使用默认值(1),则只能在同一子网内部发送。

在UdpClient类中,调用JoinMulticastGroup方法可将UdpClient对象和TTL一起加入组播组,调用DropMulticastGroup方法可退出组播组。

编写一个程序,利用组播技术向子网发送组播信息,同时接收组播的信息。

按顺序启动组播发送方与组播接收方程序,在组播发送方输入信息并单击“发送”按钮。该消息经UDP协议广播并成功的被组播接收方接收

运行结果:

Socket编程-UDP实现发送组播信息_第1张图片

源代码:

发送端:

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

namespace Socket_UdpSender
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //系统将自动分配最合适的本地地址和端口号
            UdpClient client = new UdpClient();     
            //允许发送广播    
            client.EnableBroadcast = true;
            //必须使用组播地址
            IPEndPoint p = new IPEndPoint(IPAddress.Parse("224.0.0.2"), 8001);
            //将发送内容装换为字节数组
            byte[] bytes = Encoding.UTF8.GetBytes(textSend.Text);
            try
            {
                //向子网发送信息
                client.Send(bytes, bytes.Length, p);
                textSend.Clear();
                textSend.Focus();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "发送错误");
            }
            finally
            {
                client.Close();
            }
        }
    }
}

接收端:

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

namespace Socket_UdpReceiver
{
    public partial class Form1 : Form
    {
        private  delegate void AppendStringCallBack(string text);               //定义委托
        private AppendStringCallBack OnAppendStringCallback;                    //定义回调事件
        private UdpClient client;                                               //定义udp客户端对象
        public Form1()                                                          //窗体类的构造函数
        {
            InitializeComponent();
            OnAppendStringCallback = new AppendStringCallBack(AppendString);    //绑定事件
        }

        private void AppendString(string text)                                  //定义事件方法
        {
            //Windows窗体中的控件被绑定到特定的线程,不具备线程安全性
            //因此,若从另一个线程调用控件的方法,则必须使用Invoke方法来调用封送到适当的线程
            //InvokeRequired属性用于确定是否必须调用Invoke方法
            if (textReceive.InvokeRequired)
                this.Invoke(OnAppendStringCallback, text);                      
            else
                textReceive.AppendText(text + "\r\n");        //触发事件,执行在另一个线程中订阅事件方法
        }
        //该方法先加入主播接收主播消息,再订阅事件方法AppendSting。当onAppendStringcallBack事件被触发时将
        //收到的信息添加到RichTextBox控件,以便显示消息。为了自动接收消息,ReceiveData方法不能在运行Windows
        //窗体线程中运行,须把ReceiveData创建为一个新的线程。为此,在窗体的Load事件中创建新线程。
        private void ReceiveData()
        {
            //在本机指定的端口接收
            client = new UdpClient(8001);
            IPEndPoint remove = null;
            //不知道为啥用224.0.0.1就会出现套接字无法连接主机的错误,也许是防火墙的问题?
            //加入组播,注意必须使用组播地址范围内的地址
            client.JoinMulticastGroup(IPAddress.Parse("224.0.0.2"));
            client.Ttl = 50;
         
            while (true)                            //接收从远程主机发送过来的信息
            {
                try
                {
                    byte[] bytes = client.Receive(ref remove);
                    string data = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    //订阅事件
                    AppendString(string.Format("来自{0}:{1}", remove, data));
                }
                catch
                {
                    break;                          //退出循环,结束线程
                }
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Thread showThread = new Thread(new ThreadStart(ReceiveData));
            showThread.Start();
        }
        //在关闭窗体时先关闭UdpClient
        private void Form1_FormClosing_1(object sender, FormClosingEventArgs e)
        {
            client.Close();
        }
    }
}

 

你可能感兴趣的:(网络编程)