C#下UDP通信性能探究

原文链接:C#下UDP通信性能探究 – 每天进步一点点

 

0.前言

一个项目,使用C#做UDP组播通信,发现这个过程中有丢包现象,做个测试看看哪种方式更好。

测试工具:visual studio 2022

语言:C#

框架:.netframework 4.5

网络通信库:udpClinet、socket

方式:本机收发

1.数据发送端

数据发送端用C#编写的winfrom程序,使用的是udpClient,参考代码如下:

string msg="101010EF62";//测试发送的数据
string[] str;
try
{
string ip = "224.0.0.85"; //组播地址
int port = 28889; //组播端口
System.Net.Sockets.UdpClient udpClient = new System.Net.Sockets.UdpClient();
str = Enumerable.Range(0, msg.Length / 2).Select(i => msg.Substring(i * 2, 2)).ToArray(); //分割成两个一组
byte[] res = new byte[str.Length];
for (int i = 0; i < str.Length; i++)
{
res[i] = Convert.ToByte(str[i], 16); //信息序号
}
udpClient.Send(res, res.Length, new IPEndPoint(IPAddress.Parse(ip), port));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}

注意,发送方式为没有任何间隔(一般做网络通信时要求有一定的间隔,来减少丢包率,此处为了测试性能,发送过程中没有任何间隔)

2.接收端-UdpClient方式

接收端为C#控制台程序(.netframework4.5),使用UdpClient默认方式如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
 
namespace UDP_test
{
internal class Program
{
private static UdpClient udpClient; //UDP客户端
static void Main(string[] args)
{
udpClient = new UdpClient(28889);
udpClient.JoinMulticastGroup(IPAddress.Parse("224.0.0.85")); // 加入组播组
int sum = 0;//计数器
Console.WriteLine("开始接收数据");
while (true)
{
// 接收数据
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 28889);
byte[] receiveData = udpClient.Receive(ref remoteEndPoint);
string data = BitConverter.ToString(receiveData);
//Console.WriteLine(data);
sum = sum + 1;
Console.WriteLine(DateTime.Now.ToString("mm:ss fff") + " 第" + sum);
}
}
}
}

发送211940条(每条按照218B计算,大概是211940*218/1024/1024=44MB),测试5次

发送持续时间 发送最后时间 接收最后时间 接收条数
206s 47:14 105 47:14 107 204123
176s 57:18 762 57:18 762 204026
151s 02:20 506 02:20 506 199627
162s 07:23 605 07:23 606 203649
174s 14:20 019 14:20 019 202774

我们把缓冲区加大,代码参考如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
 
namespace UDP_test
{
internal class Program
{
private static UdpClient udpClient; //UDP客户端
static void Main(string[] args)
{
udpClient = new UdpClient(28889);
udpClient.JoinMulticastGroup(IPAddress.Parse("224.0.0.85")); // 加入组播组
int sum = 0;//计数器
Console.WriteLine("开始接收数据");
udpClient.Client.ReceiveBufferSize = 8*1024*1024; //设置缓冲区
while (true)
{
// 接收数据
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 28889);
byte[] receiveData = udpClient.Receive(ref remoteEndPoint);
string data = BitConverter.ToString(receiveData);
//Console.WriteLine(data);
sum = sum + 1;
Console.WriteLine(DateTime.Now.ToString("mm:ss fff") + " 第" + sum);
}
}
}
}

结果如下:

发送持续时间 发送最后时间 接收最后时间 接收条数
158s 44:05 531 44:05 531 211940
164s 50:14 850 50:14 850 211940
154s 54:18 726 54:18 728 211940
153s 59:04 861 59:04 867 211940
160s 04:58 543 04:58 543 211940

结果发现并不丢包。

3.接收端—socket方式

参考代码如下:

//接收数据缓冲池
private static readonly ArrayPool<byte> BufferPool = ArrayPool<byte>.Shared;
 
private void ReceiveData()
{
 
// 组播地址和端口
IPAddress multicastAddress = IPAddress.Parse("224.0.0.85");
int port = 28889;
// 创建 UDP Socket
Socket receiverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// 绑定到本地端口
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
receiverSocket.Bind(localEndPoint);
// 加入组播组
receiverSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, IPAddress.Any));
// 接收数据
while (true)
{
byte[] buffer = BufferPool.Rent(1024);
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
int length = receiverSocket.ReceiveFrom(buffer, ref remoteEndPoint);
string message = BitConverter.ToString(buffer, 0, length);
Console.WriteLine(message );
}
}

经过测试,发现使用socket+缓冲池的情况下,数据接收能力更好,丢包率更低

 

posted on 2025-12-01 16:52  longkui  阅读(0)  评论(0)    收藏  举报

导航