C# 网络编程之UDP

一、概述
UDP和TCP是网络通讯常用的两个传输协议,C#一般可以通过Socket来实现UDP和TCP通讯,由于.NET框架通过UdpClient、TcpListener 、TcpClient这几个类对Socket进行了封装,使其使用更加方便, 本文就通过这几个封装过的类讲解一下相关应用。

二、UDP基本应用
与TCP通信不同,UDP通信是不分服务端和客户端的,通信双方是对等的。为了描述方便,我们把通信双方称为发送方和接收方。

发送方:

首先创建一个UDP对象:

string locateIP = "127.0.0.1"; //本机IP
 
   int locatePort = 9001;   //发送端口
 
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
 
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
 
   UdpClient udpClient = new UdpClient(locatePoint);

发送数据:

一、概述
UDP和TCP是网络通讯常用的两个传输协议,C#一般可以通过Socket来实现UDP和TCP通讯,由于.NET框架通过UdpClient、TcpListener 、TcpClient这几个类对Socket进行了封装,使其使用更加方便, 本文就通过这几个封装过的类讲解一下相关应用。

二、UDP基本应用
与TCP通信不同,UDP通信是不分服务端和客户端的,通信双方是对等的。为了描述方便,我们把通信双方称为发送方和接收方。

发送方:

首先创建一个UDP对象:

string locateIP = "127.0.0.1"; //本机IP
 
   int locatePort = 9001;   //发送端口
 
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
 
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
 
   UdpClient udpClient = new UdpClient(locatePoint);

发送数据:

string remoteIP = "127.0.0.1";    //目标机器IP
 
   int remotePort = 9002;      //接收端口   
 
   IPAddress remoteIpAddr = IPAddress.Parse(remoteIP);
 
   IPEndPoint remotePoint = new IPEndPoint(remoteIpAddr, remotePort);
 
   byte[] buffer = Encoding.UTF8.GetBytes(“hello”);
 
   udpClient.Send(buffer, buffer.Length, remotePoint);

以上就完成了一个发送任务,一个较完整的发送代码如下:

public partial class FormServer : Form
 {
  private UdpClient udpClient = null;
 
  private void btnConnect_Click(object sender, EventArgs e)
  {
   string locateIP = "127.0.0.1";
   int locatePort = 9001;
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
   udpClient = new UdpClient(locatePoint);
 
   this.groupWork.Enabled = true;
  }
 
  private void Send_Click(object sender, EventArgs e)
  {
   string text = this.txtSend.Text.Trim();
   string remoteIP = "127.0.0.1";
   int remotePort = 9002;
   byte[] buffer = Encoding.UTF8.GetBytes(text);
 
   if (udpClient != null)
   {
    IPAddress remoteIp = IPAddress.Parse(remoteIP);
    IPEndPoint remotePoint = new IPEndPoint(remoteIp, remotePort);
    udpClient.Send(buffer, buffer.Length, remotePoint);
   }
 
   Debug.WriteLine("Send OK");
  }
 }

接收端:

首先创建一个UDP对象:

string locateIP = "127.0.0.1";
 
   int locatePort = 9002;
 
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
 
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
 
   UdpClient udpClient = new UdpClient(locatePoint);

接收数据:

IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
 
  var received = udpClient.Receive(ref remotePoint);
 
  string info = Encoding.UTF8.GetString(received);
 
  string from=$” {remotePoint.Address}:{remotePoint.Port};

注意两点:

1、remotePoint是获得发送方的IP信息,定义时可以输入任何合法的IP和端口信息;

2、Receive方法是阻塞方法,所以需要在新的线程内运行,程序会一直等待接收数据,当接收到一包数据时程序就返回,要持续接收数据需要重复调用Receive方法。

一个较完整的接收端代码如下:

public partial class FormClent : Form
 {
  private UdpClient udpClient = null; 
 
  private void btnConnect_Click(object sender, EventArgs e)
  {
   string locateIP = "127.0.0.1";
   int locatePort = 9002;
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
   udpClient = new UdpClient(locatePoint);
   IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
 
   Task.Run(() =>
   {
    while (true)
    {
     if (udpClient != null)
     {
      var received = udpClient.Receive(ref remotePoint);
      string info = Encoding.UTF8.GetString(received);
      string from=$” {remotePoint.Address}:{remotePoint.Port}; 
     }
    }
   }); 
  }
 }

三、丢包和乱序问题
当发送端发送一包数据时,不管对方是否接收都是发送成功的,UDP协议本身并不会对发送的可靠性进行验证。(这里的可靠性是指是否接收到,如果对方接收到数据包,其内容还是可靠的,这个在链路层进行了保证。)同时,由于网络延时等因素,先发送的包并不能确定先被接收到,所以由于这两个原因,UDP通信存在丢包和乱序的情况。

某些业务场景下,比如实时状态监控,可能对丢包和乱序情况并不敏感, 可以不用处理,但大部分情况下还是介意丢包的,简单的处理办法就是把包的头部固定长度的空间拿出来存放核对信息,比如包编号,如果有缺失,可以要求发送方重发,也可以进行排序。

四、将数据接收包装为事件
我们对UdpClent又进行一次封装,启用一个线程进行接收数据,将接收到的数据包通过事件发布出来,这样使用起来就更方便了。

namespace Communication.UDPClient
{
 public class UdpStateEventArgs : EventArgs
 {  
  public IPEndPoint remoteEndPoint;  
  public byte[] buffer = null;
 }
 
 public delegate void UDPReceivedEventHandler(UdpStateEventArgs args);
 
 public class UDPClient
 {
  private UdpClient udpClient;
  public event UDPReceivedEventHandler UDPMessageReceived;
 
  public UDPClient(string locateIP, int locatePort)
  {
   IPAddress locateIp = IPAddress.Parse(locateIP);
   IPEndPoint locatePoint = new IPEndPoint(locateIp, locatePort);
   udpClient = new UdpClient(locatePoint);
 
   //监听创建好后,创建一个线程,开始接收信息
   Task.Run(() =>
   {
    while (true)
    {
     UdpStateEventArgs udpReceiveState = new UdpStateEventArgs();
 
     if (udpClient != null)
     {
      IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
      var received = udpClient.Receive(ref remotePoint);
      udpReceiveState.remoteEndPoint = remotePoint;
      udpReceiveState.buffer = received;
      UDPMessageReceived?.Invoke(udpReceiveState);
     }
     else
     {
      break;
     }
    }
   });
  }
 }
}

具体使用办法:

private void btnConnect_Click(object sender, EventArgs e)
  {
   string locateIP = "127.0.0.1";
   int locatePort = 9002;   
   UDPClient udpClient = new UDPClient(locateIP, locatePort);
   udpClient.UDPMessageReceived += UdpClient_UDPMessageReceived;   
  }
 
  private void UdpClient_UDPMessageReceived(UdpStateEventArgs args)
  {
   var remotePoint = args.remoteEndPoint;
   string info = Encoding.UTF8.GetString(args.buffer); 
  }

传送门:
C#网络编程入门系列包括三篇文章:

(一)C#网络编程入门之UDP

(二)C#网络编程入门之TCP

(三)C#网络编程入门之HTTP

以上就是C# 网络编程之UDP的详细内容

string remoteIP = "127.0.0.1";    //目标机器IP
 
   int remotePort = 9002;      //接收端口   
 
   IPAddress remoteIpAddr = IPAddress.Parse(remoteIP);
 
   IPEndPoint remotePoint = new IPEndPoint(remoteIpAddr, remotePort);
 
   byte[] buffer = Encoding.UTF8.GetBytes(“hello”);
 
   udpClient.Send(buffer, buffer.Length, remotePoint);

以上就完成了一个发送任务,一个较完整的发送代码如下:

public partial class FormServer : Form
 {
  private UdpClient udpClient = null;
 
  private void btnConnect_Click(object sender, EventArgs e)
  {
   string locateIP = "127.0.0.1";
   int locatePort = 9001;
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
   udpClient = new UdpClient(locatePoint);
 
   this.groupWork.Enabled = true;
  }
 
  private void Send_Click(object sender, EventArgs e)
  {
   string text = this.txtSend.Text.Trim();
   string remoteIP = "127.0.0.1";
   int remotePort = 9002;
   byte[] buffer = Encoding.UTF8.GetBytes(text);
 
   if (udpClient != null)
   {
    IPAddress remoteIp = IPAddress.Parse(remoteIP);
    IPEndPoint remotePoint = new IPEndPoint(remoteIp, remotePort);
    udpClient.Send(buffer, buffer.Length, remotePoint);
   }
 
   Debug.WriteLine("Send OK");
  }
 }

接收端:

首先创建一个UDP对象:

string locateIP = "127.0.0.1";
 
   int locatePort = 9002;
 
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
 
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
 
   UdpClient udpClient = new UdpClient(locatePoint);

接收数据:

IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
 
  var received = udpClient.Receive(ref remotePoint);
 
  string info = Encoding.UTF8.GetString(received);
 
  string from=$” {remotePoint.Address}:{remotePoint.Port};

注意两点:

1、remotePoint是获得发送方的IP信息,定义时可以输入任何合法的IP和端口信息;

2、Receive方法是阻塞方法,所以需要在新的线程内运行,程序会一直等待接收数据,当接收到一包数据时程序就返回,要持续接收数据需要重复调用Receive方法。

一个较完整的接收端代码如下:

public partial class FormClent : Form
 {
  private UdpClient udpClient = null; 
 
  private void btnConnect_Click(object sender, EventArgs e)
  {
   string locateIP = "127.0.0.1";
   int locatePort = 9002;
   IPAddress locateIpAddr = IPAddress.Parse(locateIP);
   IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
   udpClient = new UdpClient(locatePoint);
   IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
 
   Task.Run(() =>
   {
    while (true)
    {
     if (udpClient != null)
     {
      var received = udpClient.Receive(ref remotePoint);
      string info = Encoding.UTF8.GetString(received);
      string from=$” {remotePoint.Address}:{remotePoint.Port}; 
     }
    }
   }); 
  }
 }

三、丢包和乱序问题
当发送端发送一包数据时,不管对方是否接收都是发送成功的,UDP协议本身并不会对发送的可靠性进行验证。(这里的可靠性是指是否接收到,如果对方接收到数据包,其内容c#教程还是可靠的,这个在链路层进行了保证。)同时,由于网络延时等因素,先发送的包并不能确定先被接收到,所以由于这两个原因,UDP通信存在丢包和乱序的情况。

某些业务场景下,比如实时状态监控,可能对丢包和乱序情况并不敏感, 可以不用处理,但大部分情况下还是介意丢包的,简单的处理办法就是把包的头部固定长度的空间拿出来存放核对信息,比如包编号,如果有缺失,可以要求发送方重发,也可以进行排序。

四、将数据接收包装为事件
我们对UdpClent又进行一次封装,启用一个线程进行接收数据,将接收到的数据包通过事件发布出来,这样使用起来就更方便了。

namespace Communication.UDPClient
{
 public class UdpStateEventArgs : EventArgs
 {  
  public IPEndPoint remoteEndPoint;  
  public byte[] buffer = null;
 }
 
 public delegate void UDPReceivedEventHandler(UdpStateEventArgs args);
 
 public class UDPClient
 {
  private UdpClient udpClient;
  public event UDPReceivedEventHandler UDPMessageReceived;
 
  public UDPClient(string locateIP, int locatePort)
  {
   IPAddress locateIp = IPAddress.Parse(locateIP);
   IPEndPoint locatePoint = new IPEndPoint(locateIp, locatePort);
   udpClient = new UdpClient(locatePoint);
 
   //监听创建好后,创建一个线程,开始接收信息
   Task.Run(() =>
   {
    while (true)
    {
     UdpStateEventArgs udpReceiveState = new UdpStateEventArgs();
 
     if (udpClient != null)
     {
      IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
      var received = udpClient.Receive(ref remotePoint);
      udpReceiveState.remoteEndPoint = remotePoint;
      udpReceiveState.buffer = received;
      UDPMessageReceived?.Invoke(udpReceiveState);
     }
     else
     {
      break;
     }
    }
   });
  }
 }
}

具体使用办法:

private void btnConnect_Click(object sender, EventArgs e)
  {
   string locateIP = "127.0.0.1";
   int locatePort = 9002;   
   UDPClient udpClient = new UDPClient(locateIP, locatePort);
   udpClient.UDPMessageReceived += UdpClient_UDPMessageReceived;   
  }
 
  private void UdpClient_UDPMessageReceived(UdpStateEventArgs args)
  {
   var remotePoint = args.remoteEndPoint;
   string info = Encoding.UTF8.GetString(args.buffer); 
  }

传送门:
C#网络编程入门系列包括三篇文章:

(一)C#网络编程入门之UDP

(二)C#网络编程入门之TCP

(三)C#网络编程入门之HTTP

以上就是C# 网络编程之UDP的详细内容

  • 5
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值