UdpServer.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using MediaBrowser.Common.Net;
  2. using MediaBrowser.Networking.Management;
  3. using System;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Reactive.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace MediaBrowser.Networking.Udp
  10. {
  11. /// <summary>
  12. /// Provides a Udp Server
  13. /// </summary>
  14. public class UdpServer : IUdpServer
  15. {
  16. /// <summary>
  17. /// Occurs when [message received].
  18. /// </summary>
  19. public event EventHandler<UdpMessageReceivedEventArgs> MessageReceived;
  20. /// <summary>
  21. /// Raises the <see cref="E:MessageReceived" /> event.
  22. /// </summary>
  23. /// <param name="e">The <see cref="UdpMessageReceivedEventArgs" /> instance containing the event data.</param>
  24. protected virtual void OnMessageReceived(UdpMessageReceivedEventArgs e)
  25. {
  26. EventHandler<UdpMessageReceivedEventArgs> handler = MessageReceived;
  27. if (handler != null) handler(this, e);
  28. }
  29. /// <summary>
  30. /// The _udp client
  31. /// </summary>
  32. private UdpClient _udpClient;
  33. /// <summary>
  34. /// Starts the specified port.
  35. /// </summary>
  36. /// <param name="port">The port.</param>
  37. public void Start(int port)
  38. {
  39. _udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, port));
  40. _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  41. CreateObservable().Subscribe(OnMessageReceived);
  42. }
  43. /// <summary>
  44. /// Creates the observable.
  45. /// </summary>
  46. /// <returns>IObservable{UdpReceiveResult}.</returns>
  47. private IObservable<UdpReceiveResult> CreateObservable()
  48. {
  49. return Observable.Create<UdpReceiveResult>(obs =>
  50. Observable.FromAsync(() => _udpClient.ReceiveAsync())
  51. .Subscribe(obs))
  52. .Repeat()
  53. .Retry()
  54. .Publish()
  55. .RefCount();
  56. }
  57. /// <summary>
  58. /// Called when [message received].
  59. /// </summary>
  60. /// <param name="message">The message.</param>
  61. private void OnMessageReceived(UdpReceiveResult message)
  62. {
  63. var bytes = message.Buffer;
  64. OnMessageReceived(new UdpMessageReceivedEventArgs
  65. {
  66. Bytes = bytes,
  67. RemoteEndPoint = message.RemoteEndPoint.ToString()
  68. });
  69. }
  70. /// <summary>
  71. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  72. /// </summary>
  73. public void Dispose()
  74. {
  75. Dispose(true);
  76. GC.SuppressFinalize(this);
  77. }
  78. /// <summary>
  79. /// Stops this instance.
  80. /// </summary>
  81. public void Stop()
  82. {
  83. _udpClient.Close();
  84. }
  85. /// <summary>
  86. /// Releases unmanaged and - optionally - managed resources.
  87. /// </summary>
  88. /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  89. protected virtual void Dispose(bool dispose)
  90. {
  91. if (dispose)
  92. {
  93. Stop();
  94. }
  95. }
  96. /// <summary>
  97. /// Sends the async.
  98. /// </summary>
  99. /// <param name="data">The data.</param>
  100. /// <param name="ipAddress">The ip address.</param>
  101. /// <param name="port">The port.</param>
  102. /// <returns>Task{System.Int32}.</returns>
  103. /// <exception cref="System.ArgumentNullException">data</exception>
  104. public Task SendAsync(string data, string ipAddress, int port)
  105. {
  106. return SendAsync(Encoding.UTF8.GetBytes(data), ipAddress, port);
  107. }
  108. /// <summary>
  109. /// Sends the async.
  110. /// </summary>
  111. /// <param name="bytes">The bytes.</param>
  112. /// <param name="ipAddress">The ip address.</param>
  113. /// <param name="port">The port.</param>
  114. /// <returns>Task{System.Int32}.</returns>
  115. /// <exception cref="System.ArgumentNullException">bytes</exception>
  116. public Task SendAsync(byte[] bytes, string ipAddress, int port)
  117. {
  118. if (bytes == null)
  119. {
  120. throw new ArgumentNullException("bytes");
  121. }
  122. if (string.IsNullOrEmpty(ipAddress))
  123. {
  124. throw new ArgumentNullException("ipAddress");
  125. }
  126. return _udpClient.SendAsync(bytes, bytes.Length, ipAddress, port);
  127. }
  128. /// <summary>
  129. /// Sends the async.
  130. /// </summary>
  131. /// <param name="bytes">The bytes.</param>
  132. /// <param name="remoteEndPoint">The remote end point.</param>
  133. /// <returns>Task.</returns>
  134. public Task SendAsync(byte[] bytes, string remoteEndPoint)
  135. {
  136. if (bytes == null)
  137. {
  138. throw new ArgumentNullException("bytes");
  139. }
  140. if (string.IsNullOrEmpty(remoteEndPoint))
  141. {
  142. throw new ArgumentNullException("remoteEndPoint");
  143. }
  144. return _udpClient.SendAsync(bytes, bytes.Length, new NetworkManager().Parse(remoteEndPoint));
  145. }
  146. }
  147. }