using System; using global::System.Net; using global::System.Net.Sockets; using global::System.Threading; using System.Threading.Tasks; namespace Pilz.Networking { public class UDPManager : ConnectionManagerBase { public UDPManager(int port) : base(port) { cancelToken = cancelTokenSource.Token; client = new UdpClient(port); } private readonly UdpClient client; private Task listenTask = null; private readonly CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); private readonly CancellationToken cancelToken; public int MaxBufferSize { get; private set; } = 8192; ~UDPManager() { client.Client.Shutdown(SocketShutdown.Both); client.Close(); } public override void Start() { if (!IsListening) { StartInternal(); } } private void StartInternal() { IsListening = true; listenTask = Task.Run(() => { try { RetriveAnyData(cancelToken); } catch (Exception ex) { IsListening = false; } }); } public override void Stop() { if (IsListening) { IsListening = false; cancelTokenSource.Cancel(); listenTask.Wait(); } } protected override int GetBufferSize() { return MaxBufferSize; } private void RetriveAnyData(CancellationToken ct) { void doExit() => ct.ThrowIfCancellationRequested(); var receiveTask = client.ReceiveAsync(); // Wait for the data and cancel if requested receiveTask.Wait(ct); var buf = receiveTask.Result.Buffer; string ip = receiveTask.Result.RemoteEndPoint.Address.ToString(); doExit(); ProcessRetrivedData(ip, buf); doExit(); StartInternal(); } protected override void SendData(IPEndPoint ep, byte[] buf) { var udp = new UdpClient(); udp.Connect(ep); udp.Send(buf, buf.Length); udp.Client.Shutdown(SocketShutdown.Both); udp.Close(); } } }