PostSharp UDP 通信方面的基础

你好, 今天我想展示如何通过网络 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 ;).

发表评论

您的电子邮件地址不会被公开. 必需的地方已做标记 *

*

该网站使用 Akismet 来减少垃圾邮件. 了解您的评论数据的处理方式.