WsSession.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. using Microsoft.AspNetCore.Http;
  2. using Microsoft.Extensions.Primitives;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.WebSockets;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace EVCB_OCPP.WSServer.Service.WsService
  11. {
  12. public class WsSession
  13. {
  14. public WsSession()
  15. {
  16. }
  17. public PathString? Path { get; set; }
  18. public string UriScheme { get; set; }
  19. public string AuthHeader { get; set; }
  20. public string SessionID { get; set; }
  21. public IPEndPoint Endpoint { get; internal set; }
  22. public StringValues Origin { get; internal set; }
  23. public DateTime LastActiveTime { get; set; }
  24. private WebSocket _WebSocket;
  25. public WebSocket ClientWebSocket
  26. {
  27. get => _WebSocket;
  28. set
  29. {
  30. Init(value);
  31. }
  32. }
  33. public WebSocketState State => ClientWebSocket.State;
  34. public string SecWebSocketProtocol => ClientWebSocket.SubProtocol;
  35. public SemaphoreSlim EndConnSemaphore { get; } = new SemaphoreSlim(0);
  36. //public event OCPPClientDataEventHandler<WsSession, String> m_ReceiveData;
  37. public event EventHandler<string> SessionClosed;
  38. private CancellationTokenSource disconnectCancellationTokenSource = new CancellationTokenSource();
  39. private Task ReceiveLoopTask;
  40. private void Init(WebSocket webSocket)
  41. {
  42. _WebSocket = webSocket;
  43. ReceiveLoopTask = StartReceivd(webSocket, disconnectCancellationTokenSource.Token);
  44. }
  45. private async Task StartReceivd(WebSocket webSocket, CancellationToken token)
  46. {
  47. string received = string.Empty;
  48. while (!token.IsCancellationRequested)
  49. {
  50. var buffer = new byte[1024 * 4];
  51. var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), token);
  52. if (result.CloseStatus.HasValue)
  53. {
  54. _ = InternalClose(result.CloseStatus.Value);
  55. break;
  56. }
  57. received += Encoding.UTF8.GetString(buffer, 0, result.Count);
  58. //m_ReceiveData?.Invoke(this, received);
  59. LastActiveTime = DateTime.UtcNow;
  60. if (result.EndOfMessage)
  61. {
  62. HandleReceivedData(received);
  63. received = string.Empty;
  64. }
  65. }
  66. }
  67. internal virtual void HandleReceivedData(string data)
  68. {
  69. }
  70. internal void Send(string dataString)
  71. {
  72. var data = Encoding.UTF8.GetBytes(dataString);
  73. ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token);
  74. }
  75. internal void Send(byte[] data, int offset, int length)
  76. {
  77. ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token);
  78. }
  79. internal async Task Close()
  80. {
  81. string closeReason = "ServerShutdown";
  82. try
  83. {
  84. await _WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, closeReason, default);
  85. }
  86. finally
  87. {
  88. _WebSocket.Dispose();
  89. }
  90. disconnectCancellationTokenSource.Cancel();
  91. SessionClosed?.Invoke(this, closeReason.ToString());
  92. EndConnSemaphore.Release();
  93. }
  94. private async Task InternalClose(WebSocketCloseStatus closeStatus)
  95. {
  96. try
  97. {
  98. await _WebSocket.CloseAsync(closeStatus, null , default);
  99. }
  100. finally
  101. {
  102. _WebSocket.Dispose();
  103. }
  104. disconnectCancellationTokenSource.Cancel();
  105. SessionClosed?.Invoke(this, closeStatus.ToString());
  106. EndConnSemaphore.Release();
  107. }
  108. }
  109. }