C#-UDP协议通讯(一)-UDPClientHelper_Net5
代码地址:https://gitee.com/qq28069933146_admin/csharp_networkprotocol_research
视频演示:C#-TCP与UDP通讯示例演示
一、UDPClinet知识点
1、创建UDPClient客户端发送消息示例:
/// <summary>
/// 开启并发送
/// </summary>
/// <param name="iPAddress">IP</param>
/// <param name="port">端口</param>
/// <param name="sendMsg">信息</param>
/// <returns></returns>
public ResultData_TCP ConnectAndSed(string iPStr, int portStr, string sendMsg)
{
ResultData_TCP state = new ResultData_TCP();
try
{
IPAddress iPAddress = IPAddress.Parse(iPStr);
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, portStr);
byte[] sendBytes = Encoding.ASCII.GetBytes(sendMsg);
int result = _udpClient.Send(sendBytes, sendBytes.Length, iPEndPoint); // 发送信息
state = new ResultData_TCP()
{
ResultCode = 0,
ResultMsg = "发送成功!",
ResultObject1 = sendMsg
};
}
catch (SocketException e)
{
Console.WriteLine("Socket异常,错误信息: {0}", e.HResult + "_" + e.Message);
state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("SocketException:", e.HResult, ",", e.Message)
};
}
catch (Exception ex)
{
Console.WriteLine("接收出错,错误信息: {0}", ex.HResult + "_" + ex.Message);
state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("出错,错误内容: ", ex.HResult, ",", ex.Message)
};
}
finally
{
}
return state;
}
2、创建UDPClient侦听(线程+委托方法-Net 5):
/// <summary>
/// 取消线程的标识
/// </summary>
private CancellationTokenSource cts;
/// <summary>
/// 开始接收-线程
/// </summary>
/// <param name="iPEndPoint">IP与端口</param>
/// <param name="callback">委托</param>
public void BeginReceive(string iPStr,int pointStr, Action<ResultData_TCP>? callback)
{
try
{
IPAddress iPAddress = IPAddress.Parse(iPStr);
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, pointStr);
_udpClient = new UdpClient(iPEndPoint);
cts = new CancellationTokenSource();
Task.Run(() =>ThreadCode(cts.Token, iPEndPoint, callback));
}
catch (SocketException e)
{
Console.WriteLine("Socket异常,错误信息: {0}", e.HResult + "_" + e.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("SocketException:", e.HResult, ",", e.Message)
};
callback?.Invoke(state);
}
catch (Exception ex)
{
Console.WriteLine("接收出错,错误信息: {0}", ex.HResult + "_" + ex.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("出错,错误内容: ", ex.HResult, ",", ex.Message)
};
callback?.Invoke(state);
}
finally
{
}
}
/// <summary>
/// 接收
/// </summary>
/// <param name="token">线程停止标识</param>
/// <param name="iPEndPoint">IP与端口</param>
/// <param name="callback">委托</param>
private void ThreadCode(CancellationToken token, IPEndPoint iPEndPoint, Action<ResultData_TCP>? callback)
{
while (!token.IsCancellationRequested)
{
try
{
// 接收信息
byte[] receiveBytes = _udpClient.Receive(ref iPEndPoint); // 接收到的流
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("Received: {0}", returnData);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = 1,
ResultMsg = "接收成功!",
ResultObject1 = returnData, // 接收的信息
};
callback?.Invoke(state);
}
catch (SocketException e)
{
Console.WriteLine("Socket异常,错误信息: {0}", e.HResult + "_" + e.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("SocketException:", e.HResult, ",", e.Message)
};
callback?.Invoke(state);
}
catch (Exception ex)
{
Console.WriteLine("接收出错,错误信息: {0}", ex.HResult + "_" + ex.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("出错,错误内容: ", ex.HResult, ",", ex.Message)
};
callback?.Invoke(state);
}
}
_udpClient.Close(); // 关闭
}
/// <summary>
/// 停止接收-线程
/// </summary>
public void EndReceive()
{
cts.Cancel();
}
二、UDPHelper
/**
*┌──────────────────────────────────────────────────────────────┐
*│ 描 述:UDP通讯相关的工具类
*│ 作 者:执笔小白
*│ 版 本:1.0
*│ 创建时间:2022-12-18 10:40:56
*└──────────────────────────────────────────────────────────────┘
*┌──────────────────────────────────────────────────────────────┐
*│ 命名空间: ZhibiXiaobai
*│ 类 名:UDPHelper
*└──────────────────────────────────────────────────────────────┘
*/
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZhibiXiaobai;
namespace ZhibiXiaobai
{
/// <summary>
/// UDP通信帮助类-类库翻译
/// System.Net.Sockets类库
/// UDPClient
/// </summary>
public class UDPHelper
{
/// <summary>
/// UdpClient实体
/// </summary>
UdpClient _udpClient=new UdpClient();
/// <summary>
/// 取消线程的标识
/// </summary>
private CancellationTokenSource cts;
#region 属性
/// <summary>
/// 获取或设置基础网络 Socket。
/// </summary>
public Socket Client => _udpClient.Client;
/// <summary>
/// 获取从网络接收的可读取的数据量。
/// </summary>
public int Available => _udpClient.Available;
/// <summary>
/// 获取或设置 Boolean 值,该值指定 UdpClient 是否允许将 Internet 协议(IP) 数据报分段。
/// </summary>
public bool DontFragment => _udpClient.DontFragment;
/// <summary>
/// 获取或设置一个 Boolean 值,该值指定是否可以 UdpClient 发送广播数据包。
/// </summary>
public bool EnableBroadcast => _udpClient.EnableBroadcast;
/// <summary>
/// 获取或设置 Boolean 值,指定 UdpClient 是否只允许一个客户端使用端口。
/// </summary>
public bool ExclusiveAddressUse => _udpClient.ExclusiveAddressUse;
/// <summary>
/// 获取或设置 Boolean 值,该值指定是否将输出多播数据包传递给发送应用程序。
/// </summary>
public bool MulticastLoopback => _udpClient.MulticastLoopback;
/// <summary>
/// 获取或设置一个值,它指定由 UdpClient 发送的 Internet 协议(IP) 数据包的生存时间(TTL)。
/// </summary>
public short Ttl => _udpClient.Ttl;
#endregion 属性
#region 方法
/// <summary>
/// 连接 By 端口
/// 其他方式请直接使用UdpClient
/// </summary>
/// <param name="point">端口</param>
public void Connect(int point)
{
_udpClient = new UdpClient(point);
}
/// <summary>
/// 关闭 UDP 连接。
/// </summary>
/// <param name=""></param>
public void Close() => _udpClient.Close();
/// <summary>
/// 释放由 UdpClient 占用的托管和非托管资源。
/// </summary>
/// <param name=""></param>
public void Dispose() => _udpClient.Dispose();
/// <summary>
/// 启用或禁用针对 UdpClient 实例的网络地址转换(NAT) 遍历。
/// </summary>
/// <param name="isUseNAT">启用或禁用NAT遍历</param>
public void AllowNatTraversal(bool isUseNAT) => _udpClient.AllowNatTraversal(isUseNAT);
/// <summary>
/// 将 UdpClient 添加到多播组。
/// </summary>
/// <param name=""></param>
public void JoinMulticastGroup(IPAddress multicastAddr) => _udpClient.JoinMulticastGroup(multicastAddr);
/// <summary>
/// 将 UdpClient 添加到具有指定生存时间(TTL) 的多播组。
/// </summary>
/// <param name=""></param>
public void JoinMulticastGroup(IPAddress multicastAddr, int timeToLive) => _udpClient.JoinMulticastGroup(multicastAddr, timeToLive);
/// <summary>
/// 将 UdpClient 添加到多播组。
/// </summary>
/// <param name=""></param>
public void JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress) => _udpClient.JoinMulticastGroup(multicastAddr, localAddress);
/// <summary>
/// 将 UdpClient 添加到多播组。
/// </summary>
/// <param name=""></param>
public void JoinMulticastGroup(int ifindex, IPAddress multicastAddr) => _udpClient.JoinMulticastGroup(ifindex, multicastAddr);
/// <summary>
/// 退出多播组。
/// </summary>
/// <param name=""></param>
public void DropMulticastGroup(IPAddress multicastAddr) => _udpClient.DropMulticastGroup(multicastAddr);
/// <summary>
/// 退出多播组。
/// </summary>
/// <param name=""></param>
public void DropMulticastGroup(IPAddress multicastAddr, int ifindex) => _udpClient.DropMulticastGroup(multicastAddr, ifindex);
/// <summary>
/// 将数据报异步发送到远程主机。 先前已通过调用 Connect 指定目标。
/// </summary>
/// <param name=""></param>
public IAsyncResult BeginSend(byte[] datagram, int bytes, AsyncCallback? requestCallback, object? state) => _udpClient.BeginSend(datagram, bytes, requestCallback, state);
/// <summary>
/// 将数据报异步发送到目标。 目标由 EndPoint 指定。
/// </summary>
/// <param name=""></param>
public IAsyncResult BeginSend(byte[] datagram, int bytes, IPEndPoint? endPoint, AsyncCallback? requestCallback, object? state) => _udpClient.BeginSend(datagram, bytes, endPoint, requestCallback, state);
/// <summary>
/// 将数据报异步发送到目标。 目标由主机名和端口号指定。
/// </summary>
/// <param name=""></param>
public IAsyncResult BeginSend(byte[] datagram, int bytes, string? hostname, int port, AsyncCallback? requestCallback, object? state) => _udpClient.BeginSend(datagram, bytes, hostname, port, requestCallback, state);
/// <summary>
/// 结束挂起的异步发送。
/// </summary>
/// <param name=""></param>
public int EndSend(IAsyncResult asyncResult) => _udpClient.EndSend(asyncResult);
#endregion 方法
#region 接收
/// <summary>
/// 从远程主机异步接收数据报。
/// </summary>
/// <param name=""></param>
public IAsyncResult BeginReceive(AsyncCallback? requestCallback, object? state) => _udpClient.BeginReceive(requestCallback, state);
/// <summary>
/// 结束挂起的异步接收。
/// </summary>
/// <param name=""></param>
public byte[] EndReceive(IAsyncResult asyncResult, ref IPEndPoint? remoteEP) => _udpClient.EndReceive(asyncResult, ref remoteEP);
/// <summary>
/// 返回由远程主机发送的 UDP 数据报。
/// </summary>
/// <param name=""></param>
public byte[] Receive([NotNull] ref IPEndPoint? remoteEP) => _udpClient.Receive(ref remoteEP);
/// <summary>
/// 异步返回由远程主机发送的 UDP 数据报。
/// </summary>
/// <param name=""></param>
public Task<UdpReceiveResult> ReceiveAsync() => _udpClient.ReceiveAsync();
#endregion 接收
#region 发送
/// <summary>
/// 开启并发送
/// </summary>
/// <param name="iPAddress">IP</param>
/// <param name="port">端口</param>
/// <param name="sendMsg">信息</param>
/// <returns></returns>
public ResultData_TCP ConnectAndSed(string iPStr, int portStr, string sendMsg)
{
ResultData_TCP state = new ResultData_TCP();
try
{
IPAddress iPAddress = IPAddress.Parse(iPStr);
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, portStr);
byte[] sendBytes = Encoding.ASCII.GetBytes(sendMsg);
int result = _udpClient.Send(sendBytes, sendBytes.Length, iPEndPoint); // 发送信息
state = new ResultData_TCP()
{
ResultCode = 0,
ResultMsg = "发送成功!",
ResultObject1 = sendMsg
};
}
catch (SocketException e)
{
Console.WriteLine("Socket异常,错误信息: {0}", e.HResult + "_" + e.Message);
state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("SocketException:", e.HResult, ",", e.Message)
};
}
catch (Exception ex)
{
Console.WriteLine("接收出错,错误信息: {0}", ex.HResult + "_" + ex.Message);
state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("出错,错误内容: ", ex.HResult, ",", ex.Message)
};
}
finally
{
}
return state;
}
/// <summary>
/// 将 UDP 数据报发送到远程主机。
/// </summary>
/// <param name=""></param>
public int Send(byte[] datagram, int bytes) => _udpClient.Send(datagram, bytes);
/// <summary>
/// 将 UDP 数据报发送到位于指定远程终结点的主机。
/// </summary>
/// <param name=""></param>
public int Send(byte[] datagram, int bytes, IPEndPoint endPoint) => _udpClient.Send(datagram, bytes, endPoint);
/// <summary>
/// 将 UDP 数据报发送到指定远程主机上的指定端口。
/// </summary>
/// <param name=""></param>
public int Send(byte[] datagram, int bytes, string? hostname, int port) => _udpClient.Send(datagram, bytes, hostname, port);
/// <summary>
/// 将 UDP 数据报异步发送到远程主机。
/// </summary>
/// <param name=""></param>
public Task<int> SendAsync(byte[] datagram, int bytes) => _udpClient.SendAsync(datagram, bytes);
/// <summary>
/// 将 UDP 数据报异步发送到远程主机。
/// </summary>
/// <param name=""></param>
public Task<int> SendAsync(byte[] datagram, int bytes, IPEndPoint endPoint) => _udpClient.SendAsync(datagram, bytes, endPoint);
/// <summary>
/// 将 UDP 数据报异步发送到远程主机。
/// </summary>
/// <param name=""></param>
public Task<int> SendAsync(byte[] datagram, int bytes, string? hostname, int port) => _udpClient.SendAsync(datagram, bytes, hostname, port);
#endregion 发送
#region 接收-线程封装
/// <summary>
/// 开始接收-线程
/// </summary>
/// <param name="iPEndPoint">IP与端口</param>
/// <param name="callback">委托</param>
public void BeginReceive(string iPStr,int pointStr, Action<ResultData_TCP>? callback)
{
try
{
IPAddress iPAddress = IPAddress.Parse(iPStr);
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, pointStr);
_udpClient = new UdpClient(iPEndPoint);
cts = new CancellationTokenSource();
Task.Run(() =>ThreadCode(cts.Token, iPEndPoint, callback));
}
catch (SocketException e)
{
Console.WriteLine("Socket异常,错误信息: {0}", e.HResult + "_" + e.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("SocketException:", e.HResult, ",", e.Message)
};
callback?.Invoke(state);
}
catch (Exception ex)
{
Console.WriteLine("接收出错,错误信息: {0}", ex.HResult + "_" + ex.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("出错,错误内容: ", ex.HResult, ",", ex.Message)
};
callback?.Invoke(state);
}
finally
{
}
}
/// <summary>
/// 接收
/// </summary>
/// <param name="token">线程停止标识</param>
/// <param name="iPEndPoint">IP与端口</param>
/// <param name="callback">委托</param>
private void ThreadCode(CancellationToken token, IPEndPoint iPEndPoint, Action<ResultData_TCP>? callback)
{
while (!token.IsCancellationRequested)
{
try
{
// 接收信息
byte[] receiveBytes = _udpClient.Receive(ref iPEndPoint); // 接收到的流
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("Received: {0}", returnData);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = 1,
ResultMsg = "接收成功!",
ResultObject1 = returnData, // 接收的信息
};
callback?.Invoke(state);
}
catch (SocketException e)
{
Console.WriteLine("Socket异常,错误信息: {0}", e.HResult + "_" + e.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("SocketException:", e.HResult, ",", e.Message)
};
callback?.Invoke(state);
}
catch (Exception ex)
{
Console.WriteLine("接收出错,错误信息: {0}", ex.HResult + "_" + ex.Message);
ResultData_TCP state = new ResultData_TCP()
{
ResultCode = -1,
ResultMsg = string.Concat("出错,错误内容: ", ex.HResult, ",", ex.Message)
};
callback?.Invoke(state);
}
}
_udpClient.Close(); // 关闭
}
/// <summary>
/// 停止接收-线程
/// </summary>
public void EndReceive()
{
cts.Cancel();
}
#endregion 接收-线程封装
/// <summary>
/// 获取本地当前使用的Ip
/// </summary>
/// <returns></returns>
public static string GetlocalIp()
{
try
{
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect("8.8.8.8", 65530);
if (socket.LocalEndPoint is IPEndPoint endPoint)
{
return endPoint.Address.ToString();
}
else
{
return "获取IP失败!";
}
}
}
catch (Exception ex)
{
return "获取IP失败,设备未联网!";
}
}
}
/// <summary>
/// 信息载体
/// </summary>
public class ResultData_UDP
{
/// <summary>
/// 结果Code
/// 正常1,其他为异常;0不作为回复结果
/// </summary>
public int ResultCode { get; set; } = 0;
/// <summary>
/// 结果信息
/// </summary>
public string ResultMsg { get; set; } = string.Empty;
/// <summary>
/// 扩展1
/// </summary>
public object? ResultObject1 { get; set; } = string.Empty;
/// <summary>
/// 扩展2
/// </summary>
public object? ResultObject2 { get; set; } = string.Empty;
}
}
下一篇:C#-UDP协议通讯(二)-优化丢包问题
本文来自博客园,作者:꧁执笔小白꧂,转载请注明原文链接:https://www.cnblogs.com/qq2806933146xiaobai/p/17247002.html