HttpServerBase.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace HttpTest.HttpService
  9. {
  10. public abstract class HttpServerBase: IDisposable
  11. {
  12. private readonly HttpListener _listener; // HTTP 协议侦听器
  13. private readonly Thread _listenerThread; // 监听线程
  14. private readonly Thread[] _workers; // 工作线程组
  15. private readonly ManualResetEvent _stop, _ready; // 通知停止、就绪
  16. private Queue<HttpListenerContext> _queue; // 请求队列
  17. private event Action<HttpListenerContext> ProcessRequest; // 请求处理委托
  18. public HttpServerBase(int maxThreads)
  19. {
  20. _workers = new Thread[maxThreads];
  21. _queue = new Queue<HttpListenerContext>();
  22. _stop = new ManualResetEvent(false);
  23. _ready = new ManualResetEvent(false);
  24. _listener = new HttpListener();
  25. _listenerThread = new Thread(HandleRequests);
  26. }
  27. public void Start(int port)
  28. {
  29. // 注册处理函数
  30. ProcessRequest += ProcessHttpRequest;
  31. try
  32. {
  33. // 启动Http服务
  34. _listener.Prefixes.Add($"http://*:{port}/");
  35. _listener.Start();
  36. _listenerThread.Start();
  37. // 启动工作线程
  38. for (int i = 0; i < _workers.Length; i++)
  39. {
  40. _workers[i] = new Thread(Worker);
  41. _workers[i].Start();
  42. }
  43. }
  44. catch (Exception e)
  45. {
  46. Console.WriteLine(e);
  47. throw;
  48. }
  49. }
  50. // 请求处理函数
  51. protected abstract void ProcessHttpRequest(HttpListenerContext ctx);
  52. // 释放资源
  53. public void Dispose()
  54. {
  55. Stop();
  56. }
  57. // 停止服务
  58. public void Stop()
  59. {
  60. _stop.Set();
  61. _listenerThread.Join();
  62. foreach (Thread worker in _workers)
  63. {
  64. worker.Join();
  65. }
  66. _listener.Stop();
  67. }
  68. // 处理请求
  69. private void HandleRequests()
  70. {
  71. while (_listener.IsListening)
  72. {
  73. var context = _listener.BeginGetContext(ContextReady, null);
  74. if (0 == WaitHandle.WaitAny(new[] { _stop, context.AsyncWaitHandle }))
  75. {
  76. return;
  77. }
  78. }
  79. }
  80. // 请求就绪加入队列
  81. private void ContextReady(IAsyncResult ar)
  82. {
  83. try
  84. {
  85. lock (_queue)
  86. {
  87. _queue.Enqueue(_listener.EndGetContext(ar));
  88. _ready.Set();
  89. }
  90. }
  91. catch (Exception e)
  92. {
  93. Console.WriteLine($"[HttpServerBase::ContextReady]err:{e.Message}");
  94. }
  95. }
  96. // 处理一个任务
  97. private void Worker()
  98. {
  99. WaitHandle[] wait = new[] { _ready, _stop };
  100. while (0 == WaitHandle.WaitAny(wait))
  101. {
  102. HttpListenerContext context;
  103. lock (_queue)
  104. {
  105. if (_queue.Count > 0)
  106. context = _queue.Dequeue();
  107. else
  108. {
  109. _ready.Reset();
  110. continue;
  111. }
  112. }
  113. try
  114. {
  115. ProcessRequest?.Invoke(context);
  116. }
  117. catch (Exception e)
  118. {
  119. Console.WriteLine($"[HttpServerBase::Worker]err:{e.Message}");
  120. }
  121. }
  122. }
  123. }
  124. }