TService.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using Microsoft.IO;
  7. namespace KYFramework.Network
  8. {
  9. public sealed class TService : AService
  10. {
  11. private readonly Dictionary<long, TChannel> idChannels = new Dictionary<long, TChannel>();
  12. private readonly SocketAsyncEventArgs innArgs = new SocketAsyncEventArgs();
  13. private Socket acceptor;
  14. public RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
  15. public HashSet<long> needStartSendChannel = new HashSet<long>();
  16. public int PacketSizeLength { get; }
  17. /// <summary>
  18. /// 即可做client也可做server
  19. /// </summary>
  20. public TService(int packetSizeLength, IPEndPoint ipEndPoint, Action<AChannel> acceptCallback)
  21. {
  22. this.PacketSizeLength = packetSizeLength;
  23. this.AcceptCallback += acceptCallback;
  24. this.acceptor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  25. this.acceptor.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  26. this.innArgs.Completed += this.OnComplete;
  27. this.acceptor.Bind(ipEndPoint);
  28. this.acceptor.Listen(1000);
  29. this.AcceptAsync();
  30. }
  31. public TService(int packetSizeLength)
  32. {
  33. this.PacketSizeLength = packetSizeLength;
  34. }
  35. public override void Dispose()
  36. {
  37. if (this.IsDisposed)
  38. {
  39. return;
  40. }
  41. base.Dispose();
  42. foreach (long id in this.idChannels.Keys.ToArray())
  43. {
  44. TChannel channel = this.idChannels[id];
  45. channel.Dispose();
  46. }
  47. this.acceptor?.Close();
  48. this.acceptor = null;
  49. this.innArgs.Dispose();
  50. }
  51. private void OnComplete(object sender, SocketAsyncEventArgs e)
  52. {
  53. switch (e.LastOperation)
  54. {
  55. case SocketAsyncOperation.Accept:
  56. OneThreadSynchronizationContext.Instance.Post(this.OnAcceptComplete, e);
  57. break;
  58. default:
  59. throw new Exception($"socket accept error: {e.LastOperation}");
  60. }
  61. }
  62. public void AcceptAsync()
  63. {
  64. this.innArgs.AcceptSocket = null;
  65. if (this.acceptor.AcceptAsync(this.innArgs))
  66. {
  67. return;
  68. }
  69. OnAcceptComplete(this.innArgs);
  70. }
  71. private void OnAcceptComplete(object o)
  72. {
  73. if (this.acceptor == null)
  74. {
  75. return;
  76. }
  77. SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
  78. if (e.SocketError != SocketError.Success)
  79. {
  80. Log.Error($"accept error {e.SocketError}");
  81. this.AcceptAsync();
  82. return;
  83. }
  84. TChannel channel = new TChannel(e.AcceptSocket, this);
  85. this.idChannels[channel.Id] = channel;
  86. try
  87. {
  88. this.OnAccept(channel);
  89. }
  90. catch (Exception exception)
  91. {
  92. Log.Error(exception);
  93. }
  94. if (this.acceptor == null)
  95. {
  96. return;
  97. }
  98. this.AcceptAsync();
  99. }
  100. public override AChannel GetChannel(long id)
  101. {
  102. TChannel channel = null;
  103. this.idChannels.TryGetValue(id, out channel);
  104. return channel;
  105. }
  106. public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
  107. {
  108. TChannel channel = new TChannel(ipEndPoint, this);
  109. this.idChannels[channel.Id] = channel;
  110. return channel;
  111. }
  112. public override AChannel ConnectChannel(string address)
  113. {
  114. IPEndPoint ipEndPoint = NetworkHelper.ToIPEndPoint(address);
  115. return this.ConnectChannel(ipEndPoint);
  116. }
  117. public void MarkNeedStartSend(long id)
  118. {
  119. this.needStartSendChannel.Add(id);
  120. }
  121. public override void Remove(long id)
  122. {
  123. TChannel channel;
  124. if (!this.idChannels.TryGetValue(id, out channel))
  125. {
  126. return;
  127. }
  128. if (channel == null)
  129. {
  130. return;
  131. }
  132. this.idChannels.Remove(id);
  133. channel.Dispose();
  134. }
  135. public override void Update()
  136. {
  137. foreach (long id in this.needStartSendChannel)
  138. {
  139. TChannel channel;
  140. if (!this.idChannels.TryGetValue(id, out channel))
  141. {
  142. continue;
  143. }
  144. if (channel.IsSending)
  145. {
  146. continue;
  147. }
  148. try
  149. {
  150. channel.StartSend();
  151. }
  152. catch (Exception e)
  153. {
  154. Log.Error(e);
  155. }
  156. }
  157. this.needStartSendChannel.Clear();
  158. }
  159. }
  160. }