using System; using System.Net; using System.Net.Sockets; using System.Reactive.Linq; using System.Text; using System.Threading.Tasks; namespace MediaBrowser.Common.Net { /// /// Provides a Udp Server /// public class UdpServer : IObservable, IDisposable { /// /// The _udp client /// private readonly UdpClient _udpClient; /// /// The _stream /// private readonly IObservable _stream; /// /// Initializes a new instance of the class. /// /// The end point. /// endPoint public UdpServer(IPEndPoint endPoint) { if (endPoint == null) { throw new ArgumentNullException("endPoint"); } _udpClient = new UdpClient(endPoint); _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //_udpClient.ExclusiveAddressUse = false; _stream = CreateObservable(); } /// /// Creates the observable. /// /// IObservable{UdpReceiveResult}. private IObservable CreateObservable() { return Observable.Create(obs => Observable.FromAsync(() => _udpClient.ReceiveAsync()) .Subscribe(obs)) .Repeat() .Retry() .Publish() .RefCount(); } /// /// Subscribes the specified observer. /// /// The observer. /// IDisposable. /// observer public IDisposable Subscribe(IObserver observer) { if (observer == null) { throw new ArgumentNullException("observer"); } return _stream.Subscribe(observer); } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { if (dispose) { _udpClient.Close(); } } /// /// Sends the async. /// /// The data. /// The end point. /// Task{System.Int32}. /// data public async Task SendAsync(string data, IPEndPoint endPoint) { if (data == null) { throw new ArgumentNullException("data"); } if (endPoint == null) { throw new ArgumentNullException("endPoint"); } var bytes = Encoding.UTF8.GetBytes(data); return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false); } /// /// Sends the async. /// /// The bytes. /// The end point. /// Task{System.Int32}. /// bytes public async Task SendAsync(byte[] bytes, IPEndPoint endPoint) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (endPoint == null) { throw new ArgumentNullException("endPoint"); } return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false); } } }