TService.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. using Microsoft.IO;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. namespace WS
  8. {
  9. ///<summary>TCP服务</summary>
  10. public sealed class TService : AService
  11. {
  12. ///<summary>一个异步操作一个TChannel(一个Socket链接)</summary>
  13. private readonly Dictionary<long, TChannel> idChannels = new Dictionary<long, TChannel>();
  14. ///<summary>Socket异步操作</summary>
  15. private readonly SocketAsyncEventArgs innArgs = new SocketAsyncEventArgs();
  16. ///<summary>Socket</summary>
  17. private Socket server;
  18. ///<summary>性能的.NET流管理</summary>
  19. public RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
  20. ///<summary>需要开始发送的TChannel 哈希表</summary>
  21. public HashSet<long> needStartSendChannel = new HashSet<long>();
  22. ///<summary>包头长度</summary>
  23. public int PacketSizeLength { get; }
  24. /// <summary>server</summary>
  25. /// <param name="packetSizeLength">包头长度</param>
  26. /// <param name="ipEndPoint">IP 端口</param>
  27. /// <param name="acceptCallback">Accept 接收回调</param>
  28. public TService(int packetSizeLength, IPEndPoint ipEndPoint, Action<AChannel> acceptCallback)
  29. {
  30. PacketSizeLength = packetSizeLength;
  31. AcceptCallback += acceptCallback;
  32. server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建服务器监听
  33. server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  34. innArgs.Completed += OnComplete;//注册异步操作回调
  35. server.Bind(ipEndPoint);//创建Serer链接
  36. server.Listen(1000);
  37. Log.LogDebug("服务器启动成功!");
  38. AcceptAsync();
  39. }
  40. /// <summary>client</summary>
  41. public TService(int packetSizeLength)
  42. {
  43. PacketSizeLength = packetSizeLength;
  44. }
  45. public override void Dispose()
  46. {
  47. if (IsDisposed)
  48. {
  49. return;
  50. }
  51. base.Dispose();
  52. foreach (long id in idChannels.Keys.ToArray())
  53. {
  54. TChannel channel = idChannels[id];
  55. channel.Dispose();
  56. }
  57. server?.Close();
  58. server = null;
  59. innArgs.Dispose();
  60. }
  61. ///<summary>异步操作回调</summary>
  62. private void OnComplete(object sender, SocketAsyncEventArgs e)
  63. {
  64. switch (e.LastOperation)
  65. {
  66. case SocketAsyncOperation.Accept://接收客户端链接操作
  67. OneThreadSynchronizationContext.Instance.Post(OnAcceptComplete, e);
  68. break;
  69. default:
  70. throw new Exception($"socket accept error: {e.LastOperation}");
  71. }
  72. }
  73. ///<summary>接收客户端的Socket</summary>
  74. public void AcceptAsync()
  75. {
  76. innArgs.AcceptSocket = null;
  77. if (server.AcceptAsync(innArgs))//开始监听客服端链接=>如果返回值为true 表明挂起异步等待返回,如果返回值为false 表明回调完成跳过回调直接执行
  78. {
  79. return;
  80. }
  81. OnAcceptComplete(innArgs);
  82. }
  83. ///<summary>接收客户端的Socket链接完成回调</summary>
  84. private void OnAcceptComplete(object o)
  85. {
  86. if (server == null) return;
  87. SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
  88. if (e.SocketError != SocketError.Success)//如果不等于操作成功
  89. {
  90. Log.LogError($"accept error {e.SocketError}");
  91. AcceptAsync();//继续监听客户端链接
  92. return;
  93. }
  94. TChannel channel = new TChannel(e.AcceptSocket, this);//创建客户端Socket链接
  95. idChannels[channel.InstanceId] = channel;
  96. try
  97. {
  98. OnAccept(channel);//Socket链接成功 =》调用接收成功事件 到=》NetworkComponent
  99. }
  100. catch (Exception exception)
  101. {
  102. Log.LogError(exception);
  103. }
  104. if (server == null) return;
  105. AcceptAsync();//继续监听客户端链接
  106. }
  107. ///<summary>获取Channel 渠道</summary>
  108. public override AChannel GetChannel(long id)
  109. {
  110. TChannel channel = null;
  111. idChannels.TryGetValue(id, out channel);
  112. return channel;
  113. }
  114. #region -- Channel --
  115. ///<summary>链接Channel 渠道</summary>
  116. public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
  117. {
  118. TChannel channel = new TChannel(ipEndPoint, this);
  119. idChannels[channel.InstanceId] = channel;
  120. return channel;
  121. }
  122. ///<summary>链接Channel 渠道</summary>
  123. public override AChannel ConnectChannel(string address)
  124. {
  125. IPEndPoint ipEndPoint = NetworkHelper.ToIPEndPoint(address);
  126. return ConnectChannel(ipEndPoint);
  127. }
  128. ///<summary>标记需要开始发送</summary>
  129. public void MarkNeedStartSend(long id)
  130. {
  131. needStartSendChannel.Add(id);
  132. }
  133. ///<summary>删除Channel 渠道</summary>
  134. public override void Remove(long id)
  135. {
  136. TChannel channel;
  137. if (!idChannels.TryGetValue(id, out channel)) return;
  138. if (channel == null) return;
  139. idChannels.Remove(id);
  140. channel.Dispose();
  141. }
  142. #endregion
  143. public override void Update()
  144. {
  145. foreach (long id in needStartSendChannel)
  146. {
  147. TChannel channel;
  148. if (!idChannels.TryGetValue(id, out channel))
  149. continue;
  150. if (channel.IsSending)
  151. continue;
  152. try
  153. {
  154. channel.StartSend();
  155. }
  156. catch (Exception e)
  157. {
  158. Log.LogError(e);
  159. }
  160. }
  161. needStartSendChannel.Clear();
  162. }
  163. }
  164. }