原文链接: http://blog.csdn.net/humanking7/article/details/51024884

UDP的作用不用多说,在C#中不用自己痛苦的调用套接字的API,有两种方式来实现:

  1. 直接使用Socket类
  2. 使用UdpClient类

UdpClient类对基础Socket进行了封装,简化了UDP的开发难度,提高了编程效率。

话不多说,先上图。

这个程序中需要两个 UdpClient 对象,一个用于发送,一个用于接收,经测试,可以只用一个 UdpClient 对象同时进行收发,但是我的接收程序是开了一个线程,这样同时进行收和发,会出现一些问题。所以要用两个 UdpClient 对象,但是 UdpClient 不能同时绑定一个ip地址和端口 。我为此还调试了半天,发现了这个现象。
先看代码:

if ( false == isBind) { //还没有绑定 //============================ //Bind UDP //============================ //Get Local and Remote IP&Port IPAddress LocalIP = IPAddress . Parse(TxtBox_LocalIP . Text); //本地IP int LocalPort = Convert . ToInt32(TxtBox_LocalPort . Text); //本地Port m_LocalIPEndPoint = new IPEndPoint(LocalIP, LocalPort); //本地IP和Port //Bind m_UdpClientSend = new UdpClient(LocalPort); //Bind Send UDP = Local some IP&Port m_UdpClientReceive = new UdpClient(m_LocalIPEndPoint); //Bind Receive UDP = Local IP&Port 发送的UdpClient对象是m_UdpClientSend,绑定的地址是 0.0.0.0:8010 接收的UdpClient对象是m_UdpClientReceive,绑定的地址是 10.13.68.220:8010 //============================ //Start UDP Receive Thread //============================ m_ReceThread = new Thread ( new ThreadStart(ReceProcess)); //线程处理程序为 ReceProcess m_ReceThread . IsBackground = true ; //后台线程,前台线程GG,它也GG m_ReceThread . Start(); //============================ //界面处理 //============================ TxtBox_LocalPort . Enabled = false ; BTN_Bind . Text = "UnBind" ; isBind = true ; { //已经绑定 //关闭 UDP m_UdpClientSend . Close(); m_UdpClientReceive . Close(); //关闭 线程 m_ReceThread . Abort (); //界面处理 TxtBox_LocalPort . Enabled = true ; BTN_Bind . Text = "Binding" ; isBind = false ;

发送的 UdpClient 对象是 m_UdpClientSend ,绑定的地址是 0.0.0.0:8010
接收的 UdpClient 对象是 m_UdpClientReceive ,绑定的地址是 10.13.68.220:8010

接收时一定要用 m_UdpClientReceive 的,但是发送时,两个对象皆可以。

UDP的发送

发送需要对方的地址,这里的地址是 10.13.68.220:8080
发送的代码:

private void BTN_Send_Click(object sender, EventArgs e)
            if (isBind)
            {//绑定好,可发送
                IPAddress RemoteIP;   //远端 IP                
                int RemotePort;      //远端 Port
                IPEndPoint RemoteIPEndPoint; //远端 IP&Port
                if (IPAddress.TryParse(TxtBox_RemoteIP.Text, out RemoteIP) == false)//远端 IP
                    MessageBox.Show("Remote IP is Wrong!", "Wrong");
                    return;
                RemotePort = Convert.ToInt32(TxtBox_RemotePort.Text);//远端 Port
                RemoteIPEndPoint = new IPEndPoint(RemoteIP, RemotePort);//远端 IP和Port
                //Get Data
                byte[] sendBytes = System.Text.Encoding.Default.GetBytes(TxtBox_Send.Text);                
                int cnt = sendBytes.Length;
                if (0 == cnt)
                    return;
                //Send
                m_UdpClientSend.Send(sendBytes, cnt, RemoteIPEndPoint);
                //下面的代码也可以,但是接收和发送分开,更好
                //m_UdpClientReceive.Send(sendBytes, cnt, RemoteIPEndPoint);
                //CNT
                m_cntSend += cnt;
                SetCNTTextBox();
                MessageBox.Show("You need bind first!","UnBind");

核心代码就是一句:

m_UdpClientSend.Send(sendBytes, cnt, RemoteIPEndPoint);
  • RemoteIPEndPoint 是记录目标机的IP和端口号的IPEndPoint类型变量
  • sendBytes是用于发送的 byte[] 数组
  • cnt 记录要发送的byte长度

UDP的接收

接收要开一个线程,用于接收数据

private Thread m_ReceThread;//接收线程

线程的设置,在绑定按钮的click响应函数中,在解绑和窗体关闭时,都要将线程关掉

if (false == isBind)
{//还没有绑定
    //other code
    //······
    //============================
    //Start UDP Receive Thread
    //============================
    m_ReceThread = new Thread(new ThreadStart(ReceProcess));//线程处理程序为 ReceProcess
    m_ReceThread.IsBackground = true;//后台线程,前台线程GG,它也GG
    m_ReceThread.Start();
    //other code
    //······
//已经绑定
     //关闭 UDP
     m_UdpClientSend.Close();
     m_UdpClientReceive.Close();
     //关闭 线程
     m_ReceThread.Abort();
     //界面处理
     TxtBox_LocalPort.Enabled = true;
     BTN_Bind.Text = "Binding";
     isBind = false;

线程设定为后台线程

m_ReceThread.IsBackground = true;

这样的好处是,当主线程结束时,这个线程也跟着结束,防止了没有释放线程带来的开销和bug

线程的处理函数代码如下:

/// <summary>
/// 在后台运行的接收线程
/// </summary>
private void ReceProcess()
    int cnt = 0;
    string receiveFromOld = "";
    string receiveFromNew = "";
    //定义IPENDPOINT,装载远程IP地址和端口 
    IPEndPoint remoteIpAndPort = new IPEndPoint(IPAddress.Any, 0);
    while (true)
        byte[] ReceiveBytes = m_UdpClientReceive.Receive(ref remoteIpAndPort);
        cnt = ReceiveBytes.Length;
        receiveFromNew = remoteIpAndPort.ToString();
        if (!receiveFromNew.Equals(receiveFromOld))
            receiveFromOld = receiveFromNew;
            string str_From = String.Format("\r\n【Receive from {0}】\r\n", receiveFromNew);
            TxtBox_Receive.Text += str_From;
        string str = System.Text.Encoding.Default.GetString(ReceiveBytes, 0, cnt);
        //界面显示
        TxtBox_Receive.Text += str;
        m_cntReceive += cnt;
        SetCNTTextBox();

其中要注意的就是接收函数 Receive()参数 ,这个这个参数是一个 IPEndPoint 变量,而且是一个 引用参数,它的初始化也很有讲究

IPEndPoint remoteIpAndPort = new IPEndPoint(IPAddress.Any, 0);

被函数 Receive() 调用后,remoteIpAndPort的值将会发生改变,得到发送方的IP地址和端口号,最后我通过 IPEndPoint 类的ToString()方法,将其打印出来,用于显示对方的IP。

【注意】: 发送数据给你的IP地址和端口,不一定是你要发送的远端IP地址和端口。而且你可以接收到任何一个IP地址和端口发送的数据。

byte[] ReceiveBytes = m_UdpClientReceive.Receive(ref remoteIpAndPort); string str_From = String.Format("\r\n【Receive from {0}】\r\n", receiveFromNew); 原创文章,欢迎转载。转载请注明:转载自 祥的博客原文链接:http://blog.csdn.net/humanking7/article/details/51024884UDP的作用不用多说,在C#中不用自己痛苦的调用套接字的API,有两种方式来实现:直接使用Socket类使用UdpClient类UdpClient类对基础Socket进行了封装,简化了UDP的开发难度,提高了编程效率。话不多说
richTextBox1.Text = string.Empty; //实例化UdpClient对象 UdpClient udpclient = new UdpClient(Convert.ToInt32(textBox2.Text)); //调用UdpClient对象的Connect建立默认远程主机 udpclient.Connect(textBox1.Text, Convert.ToInt32(textBox2.Text)); //定义一个字节数组,用来存放发送到远程主机的信息 Byte[] sendBytes = Encoding.Default.GetBytes(textBox3.Text); //调用UdpClient对象的Send方法将Udp数据报发送到远程主机 udpclient.Send(sendBytes, sendBytes.Length); //实例化IPEndPoint对象,用来显示响应主机的标识 IPEndPoint ipendpoint = new IPEndPoint(IPAddress.Any, 0); //调用UdpClient对象的Receive方法获得从远程主机返回的Udp数据报 Byte[] receiveBytes = udpclient.Receive(ref ipendpoint);
使用Socket进行通信中,UDP是一种轻量级的无连接的通信协议。相对于TCP的安全可靠且又可以双工通信,UDP则更强调简单高效,而且利用UDP的无连接特性,我们可以穿透局域网,很多时候能够实现TCP无法实现的功能。 本文共分为三个部分: 第一部分 UDP的基本通信开始方法。 第二部分 UDP公网通信测试 第三部分 双局域网不利用第三方公共服务器实现直接通信。 这是第一部分。 全文主要的实现方法为...
1、UDP(User Data Protocol,用户数据报协议) (1) UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。 (2) 由于传输数据
之前困恼了很久的问题,终于解决了,项目要求使用Upd传输,128000的采样率 ,每次一个通道2000个数据,一个数据用3个字节传输,共8通道,最后两字节验证码,最后计算转成double值,用曲线显示并保存文件。 128000/2000=62(次) 1/62≈0.016(s)=16(ms) 200038+2=48002(字节) 相当于循环16ms传输48002个字节。 在之前的项目中,没有解决,让c++的同事写的插件,空闲时还是要自己研究下哈,但是资料真的好难找,最后自己摸索,实现了,下面把帮助类贴
UDP不属于面向连接的通信,在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和QQ就是使用的UDP协议。 我们通过UDP
// 构造一个远程终结点 IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 11000); // 发送数据 string message = "hello, world"; byte[] data = Encoding.UTF8.GetBytes(message); udpClient.Send(data, data.Length, ipEndPoint); // 接收数据 byte[] receiveBytes = udpClient.Receive(ref ipEndPoint); string receiveMessage = Encoding.UTF8.GetString(receiveBytes); Console.WriteLine($"Received: {receiveMessage}"); catch (Exception e) Console.WriteLine(e.ToString()); finally udpClient.Close(); Console.ReadLine(); 在这个示例中,我们创建了一个UdpClient对象,并绑定了本地端口11000。然后构造了一个远程终结点,将数据发送给远程终结点,接收远程终结点返回的数据。在发送数据时,我们将字符串转换成字节数组,使用UdpClient的Send方法发送;在接收数据时,我们调用UdpClient的Receive方法,该方法返回一个字节数组,我们将其转换成字符串并输出。最后关闭UdpClient对象并等待用户按下Enter键退出程序。