UdpServer.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Reactive.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace MediaBrowser.Common.Net
  8. {
  9. /// <summary>
  10. /// Provides a Udp Server
  11. /// </summary>
  12. public class UdpServer : IObservable<UdpReceiveResult>, IDisposable
  13. {
  14. /// <summary>
  15. /// The _udp client
  16. /// </summary>
  17. private readonly UdpClient _udpClient;
  18. /// <summary>
  19. /// The _stream
  20. /// </summary>
  21. private readonly IObservable<UdpReceiveResult> _stream;
  22. /// <summary>
  23. /// Initializes a new instance of the <see cref="UdpServer" /> class.
  24. /// </summary>
  25. /// <param name="endPoint">The end point.</param>
  26. /// <exception cref="System.ArgumentNullException">endPoint</exception>
  27. public UdpServer(IPEndPoint endPoint)
  28. {
  29. if (endPoint == null)
  30. {
  31. throw new ArgumentNullException("endPoint");
  32. }
  33. _udpClient = new UdpClient(endPoint);
  34. _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  35. //_udpClient.ExclusiveAddressUse = false;
  36. _stream = CreateObservable();
  37. }
  38. /// <summary>
  39. /// Creates the observable.
  40. /// </summary>
  41. /// <returns>IObservable{UdpReceiveResult}.</returns>
  42. private IObservable<UdpReceiveResult> CreateObservable()
  43. {
  44. return Observable.Create<UdpReceiveResult>(obs =>
  45. Observable.FromAsync(() => _udpClient.ReceiveAsync())
  46. .Subscribe(obs))
  47. .Repeat()
  48. .Retry()
  49. .Publish()
  50. .RefCount();
  51. }
  52. /// <summary>
  53. /// Subscribes the specified observer.
  54. /// </summary>
  55. /// <param name="observer">The observer.</param>
  56. /// <returns>IDisposable.</returns>
  57. /// <exception cref="System.ArgumentNullException">observer</exception>
  58. public IDisposable Subscribe(IObserver<UdpReceiveResult> observer)
  59. {
  60. if (observer == null)
  61. {
  62. throw new ArgumentNullException("observer");
  63. }
  64. return _stream.Subscribe(observer);
  65. }
  66. /// <summary>
  67. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  68. /// </summary>
  69. public void Dispose()
  70. {
  71. Dispose(true);
  72. GC.SuppressFinalize(this);
  73. }
  74. /// <summary>
  75. /// Releases unmanaged and - optionally - managed resources.
  76. /// </summary>
  77. /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  78. protected virtual void Dispose(bool dispose)
  79. {
  80. if (dispose)
  81. {
  82. _udpClient.Close();
  83. }
  84. }
  85. /// <summary>
  86. /// Sends the async.
  87. /// </summary>
  88. /// <param name="data">The data.</param>
  89. /// <param name="endPoint">The end point.</param>
  90. /// <returns>Task{System.Int32}.</returns>
  91. /// <exception cref="System.ArgumentNullException">data</exception>
  92. public async Task<int> SendAsync(string data, IPEndPoint endPoint)
  93. {
  94. if (data == null)
  95. {
  96. throw new ArgumentNullException("data");
  97. }
  98. if (endPoint == null)
  99. {
  100. throw new ArgumentNullException("endPoint");
  101. }
  102. var bytes = Encoding.UTF8.GetBytes(data);
  103. return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false);
  104. }
  105. /// <summary>
  106. /// Sends the async.
  107. /// </summary>
  108. /// <param name="bytes">The bytes.</param>
  109. /// <param name="endPoint">The end point.</param>
  110. /// <returns>Task{System.Int32}.</returns>
  111. /// <exception cref="System.ArgumentNullException">bytes</exception>
  112. public async Task<int> SendAsync(byte[] bytes, IPEndPoint endPoint)
  113. {
  114. if (bytes == null)
  115. {
  116. throw new ArgumentNullException("bytes");
  117. }
  118. if (endPoint == null)
  119. {
  120. throw new ArgumentNullException("endPoint");
  121. }
  122. return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false);
  123. }
  124. }
  125. }