TcpServerChannel.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. using Top.Api;
  7. namespace Taobao.Top.Link.Channel.TCP
  8. {
  9. /// <summary>server channel bind on raw tcp, just impl an easy server
  10. /// </summary>
  11. public class TcpServerChannel : ServerChannel
  12. {
  13. private bool _running;
  14. private TcpListener _tcpListener;
  15. private Thread _acceptWorker;
  16. private IOWorker _ioWorker;
  17. private int _ioWorkerCount;
  18. private LinkedList<TcpClient> _tcpClients;
  19. public delegate void IOWorker(ITopLogger log, TcpServerChannel server, TcpClient tcpClient);
  20. /// <summary>init tcp server channel
  21. /// </summary>
  22. /// <param name="factory"></param>
  23. /// <param name="port"></param>
  24. /// <param name="ioWorker">deal with networkstream</param>
  25. public TcpServerChannel(ITopLogger log
  26. , int port
  27. , IOWorker ioWorker)
  28. : base(log
  29. , port)
  30. {
  31. this._ioWorker = ioWorker;
  32. this._tcpClients = new LinkedList<TcpClient>();
  33. }
  34. public override void Start()
  35. {
  36. this._running = true;
  37. this._tcpListener = new TcpListener(IPAddress.Any, this.Port);
  38. this._tcpListener.Start();
  39. this._acceptWorker = new Thread(() =>
  40. {
  41. while (this._running)
  42. {
  43. try
  44. {
  45. var client = this._tcpListener.AcceptTcpClient();
  46. this._tcpClients.AddLast(client);
  47. ThreadPool.QueueUserWorkItem((state) =>
  48. {
  49. try { this.AcceptSocket(client); }
  50. catch (Exception e)
  51. {
  52. this.InternalOnError(e);
  53. this._tcpClients.Remove(client);
  54. }
  55. });
  56. }
  57. catch (SocketException) { break; }
  58. catch (Exception e)
  59. {
  60. this.InternalOnError(e);
  61. break;
  62. }
  63. }
  64. });
  65. this._acceptWorker.IsBackground = true;
  66. this._acceptWorker.Start();
  67. }
  68. public override void Stop()
  69. {
  70. this._running = false;
  71. this._acceptWorker.Abort();
  72. this._tcpListener.Stop();
  73. }
  74. private void AcceptSocket(TcpClient client)
  75. {
  76. if (this._ioWorker == null)
  77. return;
  78. var logName = "IO-Worker#" + (++this._ioWorkerCount);
  79. ThreadPool.QueueUserWorkItem(o =>
  80. this._ioWorker(Log.Instance, this, client));
  81. }
  82. private void InternalOnError(Exception e)
  83. {
  84. if (this.OnError != null)
  85. this.OnError(this, new ChannelContext(e));
  86. }
  87. }
  88. }