相关文章推荐
机灵的烈马  ·  重庆市医疗保障局办公室关于公布2023年国家 ...·  1 年前    · 
考研的麦片  ·  “random_shuffle”:不是“st ...·  1 年前    · 
独立的红豆  ·  山西大学科学技术哲学研究中心·  1 年前    · 
老实的电梯  ·  2023 ...·  1 年前    · 
精明的手术刀  ·  《关于支持山区26县就业创业高质量发展的若干 ...·  1 年前    · 
Code  ›  [C#]UDP通讯开发者社区
线程 udp
https://cloud.tencent.com/developer/article/1596248
坚强的大蒜
2 年前
作者头像
祥知道
0 篇文章

[C#]UDP通讯

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 祥的专栏 > [C#]UDP通讯

[C#]UDP通讯

作者头像
祥知道
发布 于 2020-03-10 15:07:42
917 0
发布 于 2020-03-10 15:07:42
举报

原创文章,欢迎转载。转载请注明:转载自 祥的博客

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


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

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

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

话不多说,先上图。

01

重点

这个程序中需要两个 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();
 
推荐文章
机灵的烈马  ·  重庆市医疗保障局办公室关于公布2023年国家医保谈判药品门诊保障用药名单的通知_重庆市医疗保障局
1 年前
考研的麦片  ·  “random_shuffle”:不是“std”错误的成员_hypot’不是‘std’的成员-CSDN博客
1 年前
独立的红豆  ·  山西大学科学技术哲学研究中心
1 年前
老实的电梯  ·  2023 年,谷歌翻译又失效,“手把手”教你复活! - 少数派
1 年前
精明的手术刀  ·  《关于支持山区26县就业创业高质量发展的若干意见》政策解读
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号