Base of The PostSharp UDP Communication Aspect

안녕, Today I would like to show how Simple is communicate via network UDP. I sometimes saw how some developers try to prepare that kind of communication with more code in C# that can be very easy. I would like to only show you an example. And ask you, is it enough to communicate? 물론, it is a class that can be very easily used as the base of the PostSharp Communication Aspect. I think that you can easily encapsulate that code into an aspect ;).

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();
    }
  }
}

So in my PC an output is:

Sending 100000 trivial UDP packets takes about 4693 ms.

What do you think is it 469 ms is enough for 10 000 parallel packets? Why do most developers write more code for those kinds of solutions?

Ok so, that I will change my solutions a bit to something worst.

[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);
}

And after that changes everything looks very cool and an output is:

Sending 100000 trivial UDP packets takes about 2358 ms.

피 ;).

답장을 남겨주세요

귀하의 이메일 주소는 공개되지 않습니다. 필요 입력 사항은 표시되어 있습니다 *

*

이 사이트는 스팸을 줄이기 위해 Akismet을 사용합니다.. 댓글 데이터가 처리되는 방법 알아보기.