你好, 今天我想展示如何通过网络 UDP 进行 Simple 通信. 我有时会看到一些开发人员尝试用 C# 编写更多代码来准备这种通信,这很容易. 我只想给你举个例子. 并问你, 沟通够了吗? 当然, 它是一个可以非常轻松地用作 PostSharp 通信方面的基础的类. 我认为您可以轻松地将该代码封装到一个方面中 ;).
namespace UdpCommunicationExample { using System; using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; using System.Runtime.CompilerServices; using System.Threading.Tasks; public class UdpCommunicationClient { private readonly UdpClient udpClient; public UdpCommunicationClient(IPEndPoint clientIpEndPoint) { udpClient = new UdpClient(clientIpEndPoint); } [MethodImpl(MethodImplOptions.Synchronized)] public bool SendData(byte[] datagram, IPEndPoint serverIpEndPoint) { lock (this) { while (!udpClient.Client.Poll(100, SelectMode.SelectWrite)) ; var asyncResult = udpClient.BeginSend( datagram, datagram.Length, serverIpEndPoint, null, null); asyncResult.AsyncWaitHandle.WaitOne(Timeout.Infinite); return datagram.Length == udpClient.EndSend(asyncResult); } } } public class UdpCommunicationServer { private readonly UdpClient udpClientListener; public delegate void UdpCommunicatorDatagramReceived(byte[] datagram); public event UdpCommunicatorDatagramReceived DatagramReceived; public UdpCommunicationServer(IPEndPoint serverIpEndPoint) { udpClientListener = new UdpClient(serverIpEndPoint); new Thread(StartUdpListener) { IsBackground = true }.Start(); } private void StartUdpListener() { do { IPEndPoint ipEndPoint = null; var asyncResult = udpClientListener.BeginReceive(null, null); asyncResult.AsyncWaitHandle.WaitOne(Timeout.Infinite); var datagram = udpClientListener.EndReceive(asyncResult, ref ipEndPoint); DatagramRecived(datagram); } while (true); } private void DatagramRecived(byte[] datagram) { if (DatagramReceived != null) DatagramReceived(datagram); } } public class Program { static void Main() { var serverIpEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2000); var clientIpEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.2"), 2000); var udpComunicationServer = new UdpCommunicationServer(serverIpEndPoint); var udpComunicationClient = new UdpCommunicationClient(clientIpEndPoint); var packetCount = 0; udpComunicationServer.DatagramReceived += datagram => Interlocked.Increment(ref packetCount); var stopwatch = Stopwatch.StartNew(); Parallel.For(0, 20000, i => { udpComunicationClient .SendData(new byte[] { 1,2,3,4,5,6,7,8,9,10 }, serverIpEndPoint); udpComunicationClient .SendData(new byte[] { 2,2,3,4,5,6,7,8,9,10 }, serverIpEndPoint); udpComunicationClient .SendData(new byte[] { 3,2,3,4,5,6,7,8,9,10 }, serverIpEndPoint); udpComunicationClient .SendData(new byte[] { 4,2,3,4,5,6,7,8,9,10 }, serverIpEndPoint); udpComunicationClient .SendData(new byte[] { 5,2,3,4,5,6,7,8,9,10 }, serverIpEndPoint); }); stopwatch.Stop(); Thread.Sleep(4); Console.WriteLine(@"Sending {0} trivial UDP packets takes about {1} ms.", packetCount, stopwatch.ElapsedMilliseconds); Console.ReadKey(); } } }
因此在我的电脑中输出是:
Sending 100000 trivial UDP packets takes about 4693 ms.
你认为它是什么 469 ms 就足够了 10 000 并行数据包? 为什么大多数开发人员为这些解决方案编写更多代码?
好的,, 我会稍微改变一下我的解决方案,以应对更糟糕的事情.
[MethodImpl(MethodImplOptions.Synchronized)] public bool SendData(byte[] datagram, IPEndPoint serverIpEndPoint) { lock (this) { while (!udpClient.Client.Poll(100, SelectMode.SelectWrite)) ; return datagram.Length == udpClient.Send( datagram, datagram.Length, serverIpEndPoint); } }
private void StartUdpListener() { do { IPEndPoint ipEndPoint = null; var datagram = udpClientListener.Receive(ref ipEndPoint); DatagramRecived(datagram); } while (true); }
经过这些改变之后,一切看起来都很酷,输出是:
Sending 100000 trivial UDP packets takes about 2358 ms.
p ;).