WsServer.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. using System;
  2. using System.Net;
  3. using System.Text;
  4. namespace NetCoreServer
  5. {
  6. /// <summary>
  7. /// WebSocket server
  8. /// </summary>
  9. /// <remarks> WebSocket server is used to communicate with clients using WebSocket protocol. Thread-safe.</remarks>
  10. public class WsServer : HttpServer, IWebSocket
  11. {
  12. internal readonly WebSocket WebSocket;
  13. /// <summary>
  14. /// Initialize WebSocket server with a given IP address and port number
  15. /// </summary>
  16. /// <param name="address">IP address</param>
  17. /// <param name="port">Port number</param>
  18. public WsServer(IPAddress address, int port) : base(address, port) { WebSocket = new WebSocket(this); }
  19. /// <summary>
  20. /// Initialize WebSocket server with a given IP address and port number
  21. /// </summary>
  22. /// <param name="address">IP address</param>
  23. /// <param name="port">Port number</param>
  24. public WsServer(string address, int port) : base(address, port) { WebSocket = new WebSocket(this); }
  25. /// <summary>
  26. /// Initialize WebSocket server with a given DNS endpoint
  27. /// </summary>
  28. /// <param name="endpoint">DNS endpoint</param>
  29. public WsServer(DnsEndPoint endpoint) : base(endpoint) { WebSocket = new WebSocket(this); }
  30. /// <summary>
  31. /// Initialize WebSocket server with a given IP endpoint
  32. /// </summary>
  33. /// <param name="endpoint">IP endpoint</param>
  34. public WsServer(IPEndPoint endpoint) : base(endpoint) { WebSocket = new WebSocket(this); }
  35. #region Session management
  36. public virtual bool CloseAll() => CloseAll(0, Span<byte>.Empty);
  37. public virtual bool CloseAll(int status) => CloseAll(status, Span<byte>.Empty);
  38. public virtual bool CloseAll(int status, string text) => CloseAll(status, Encoding.UTF8.GetBytes(text));
  39. public virtual bool CloseAll(int status, ReadOnlySpan<char> text) => CloseAll(status, Encoding.UTF8.GetBytes(text.ToArray()));
  40. public virtual bool CloseAll(int status, byte[] buffer) => CloseAll(status, buffer.AsSpan());
  41. public virtual bool CloseAll(int status, byte[] buffer, long offset, long size) => CloseAll(status, buffer.AsSpan((int)offset, (int)size));
  42. public virtual bool CloseAll(int status, ReadOnlySpan<byte> buffer)
  43. {
  44. lock (WebSocket.WsSendLock)
  45. {
  46. WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, buffer, status);
  47. if (!Multicast(WebSocket.WsSendBuffer.AsSpan()))
  48. return false;
  49. return base.DisconnectAll();
  50. }
  51. }
  52. #endregion
  53. #region Multicasting
  54. public override bool Multicast(ReadOnlySpan<byte> buffer)
  55. {
  56. if (!IsStarted)
  57. return false;
  58. if (buffer.IsEmpty)
  59. return true;
  60. // Multicast data to all WebSocket sessions
  61. foreach (var session in Sessions.Values)
  62. {
  63. if (session is WsSession wsSession)
  64. {
  65. if (wsSession.WebSocket.WsHandshaked)
  66. wsSession.SendAsync(buffer);
  67. }
  68. }
  69. return true;
  70. }
  71. #endregion
  72. #region WebSocket multicast text methods
  73. public bool MulticastText(string text) => MulticastText(Encoding.UTF8.GetBytes(text));
  74. public bool MulticastText(ReadOnlySpan<char> text) => MulticastText(Encoding.UTF8.GetBytes(text.ToArray()));
  75. public bool MulticastText(byte[] buffer) => MulticastText(buffer.AsSpan());
  76. public bool MulticastText(byte[] buffer, long offset, long size) => MulticastText(buffer.AsSpan((int)offset, (int)size));
  77. public bool MulticastText(ReadOnlySpan<byte> buffer)
  78. {
  79. lock (WebSocket.WsSendLock)
  80. {
  81. WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_TEXT, false, buffer);
  82. return Multicast(WebSocket.WsSendBuffer.AsSpan());
  83. }
  84. }
  85. #endregion
  86. #region WebSocket multicast binary methods
  87. public bool MulticastBinary(string text) => MulticastBinary(Encoding.UTF8.GetBytes(text));
  88. public bool MulticastBinary(ReadOnlySpan<char> text) => MulticastBinary(Encoding.UTF8.GetBytes(text.ToArray()));
  89. public bool MulticastBinary(byte[] buffer) => MulticastBinary(buffer.AsSpan());
  90. public bool MulticastBinary(byte[] buffer, long offset, long size) => MulticastBinary(buffer.AsSpan((int)offset, (int)size));
  91. public bool MulticastBinary(ReadOnlySpan<byte> buffer)
  92. {
  93. lock (WebSocket.WsSendLock)
  94. {
  95. WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_BINARY, false, buffer);
  96. return Multicast(WebSocket.WsSendBuffer.AsSpan());
  97. }
  98. }
  99. #endregion
  100. #region WebSocket multicast ping methods
  101. public bool MulticastPing(string text) => MulticastPing(Encoding.UTF8.GetBytes(text));
  102. public bool MulticastPing(ReadOnlySpan<char> text) => MulticastPing(Encoding.UTF8.GetBytes(text.ToArray()));
  103. public bool MulticastPing(byte[] buffer) => MulticastPing(buffer.AsSpan());
  104. public bool MulticastPing(byte[] buffer, long offset, long size) => MulticastPing(buffer.AsSpan((int)offset, (int)size));
  105. public bool MulticastPing(ReadOnlySpan<byte> buffer)
  106. {
  107. lock (WebSocket.WsSendLock)
  108. {
  109. WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_PING, false, buffer);
  110. return Multicast(WebSocket.WsSendBuffer.AsSpan());
  111. }
  112. }
  113. #endregion
  114. protected override TcpSession CreateSession() { return new WsSession(this); }
  115. }
  116. }