WService.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #if !UNITY_WEBGL
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Net;
  6. using System.Net.WebSockets;
  7. namespace ET
  8. {
  9. public class WService: AService
  10. {
  11. private long idGenerater = 200000000;
  12. private HttpListener httpListener;
  13. private readonly Dictionary<long, WChannel> channels = new Dictionary<long, WChannel>();
  14. public WService(ThreadSynchronizationContext threadSynchronizationContext, IEnumerable<string> prefixs)
  15. {
  16. this.ThreadSynchronizationContext = threadSynchronizationContext;
  17. this.httpListener = new HttpListener();
  18. StartAccept(prefixs).Coroutine();
  19. }
  20. public WService(ThreadSynchronizationContext threadSynchronizationContext)
  21. {
  22. this.ThreadSynchronizationContext = threadSynchronizationContext;
  23. }
  24. private long GetId
  25. {
  26. get
  27. {
  28. return ++this.idGenerater;
  29. }
  30. }
  31. public WChannel Create(string address, long id)
  32. {
  33. ClientWebSocket webSocket = new ClientWebSocket();
  34. WChannel channel = new WChannel(id, webSocket, address, this);
  35. this.channels[channel.Id] = channel;
  36. return channel;
  37. }
  38. public override void Remove(long id)
  39. {
  40. WChannel channel;
  41. if (!this.channels.TryGetValue(id, out channel))
  42. {
  43. return;
  44. }
  45. this.channels.Remove(id);
  46. channel.Dispose();
  47. }
  48. public override bool IsDispose()
  49. {
  50. return this.httpListener == null;
  51. }
  52. protected void Get(long id, string address)
  53. {
  54. if (!this.channels.TryGetValue(id, out _))
  55. {
  56. this.Create(address, id);
  57. }
  58. }
  59. public override void Dispose()
  60. {
  61. this.ThreadSynchronizationContext = null;
  62. this.httpListener?.Close();
  63. this.httpListener = null;
  64. }
  65. private async ETTask StartAccept(IEnumerable<string> prefixs)
  66. {
  67. try
  68. {
  69. foreach (string prefix in prefixs)
  70. {
  71. this.httpListener.Prefixes.Add(prefix);
  72. Log.Console($"start {prefix}");
  73. }
  74. httpListener.Start();
  75. while (true)
  76. {
  77. var context = await this.httpListener.GetContextAsync();
  78. Log.Info($"Accept WebSocket {context.Request.RemoteEndPoint}");
  79. //跨域设置
  80. {
  81. context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
  82. context.Response.AddHeader("Access-Control-Allow-Headers", "content-type, Signature, Timestamp, Token");
  83. context.Response.AddHeader("Access-Control-Allow-Methods", "POST");
  84. context.Response.AddHeader("Access-Control-Allow-Origin", "*");
  85. if (context.Request.HttpMethod == "OPTIONS")
  86. {
  87. context.Response.StatusCode = 204;
  88. }
  89. }
  90. if (context.Request.IsWebSocketRequest)
  91. {
  92. var webSocket = await context.AcceptWebSocketAsync(null);
  93. WChannel channel = new WChannel(this.GetId, webSocket.WebSocket, this, context.Request.RemoteEndPoint);
  94. this.channels[channel.Id] = channel;
  95. this.OnAccept(channel.Id, channel.RemoteAddress);
  96. }
  97. else
  98. {
  99. context.Response.StatusCode = 400;
  100. context.Response.Close();
  101. }
  102. }
  103. }
  104. catch (HttpListenerException e)
  105. {
  106. if (e.ErrorCode == 5)
  107. {
  108. throw new Exception($"CMD管理员中输入: netsh http add urlacl url=http://{string.Join(",", prefixs)}/ user=Everyone", e);
  109. }
  110. Log.Error(e);
  111. }
  112. catch (Exception e)
  113. {
  114. Log.Error(e);
  115. }
  116. }
  117. protected override void Get(long id, IPEndPoint address)
  118. {
  119. // 将IPEndPoint转换为WebSocket适用的地址格式(ws://或wss://)
  120. string webSocketAddress = $"ws://{address.Address}:{address.Port}";
  121. // 检查是否已存在该通道
  122. if (!this.channels.TryGetValue(id, out _))
  123. {
  124. // 不存在则创建新的WebSocket连接
  125. this.Create(webSocketAddress, id);
  126. } }
  127. protected override void Send(long channelId, long actorId, MemoryStream stream)
  128. {
  129. this.channels.TryGetValue(channelId, out WChannel channel);
  130. if (channel == null)
  131. {
  132. return;
  133. }
  134. channel.Send(stream);
  135. }
  136. public override void Update()
  137. {
  138. }
  139. }
  140. }
  141. #endif