using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Threading; using Sog; using SimpleHttpServer; namespace SMWebServer { internal class HttpRequestInfo { public HttpContext Http; public DateTime BeginTime; public bool StartProcess;//是否开始处理 public bool ProcessEnd; //是否处理完毕 public int ProcessResult; //错误码 } public class TokenInfo { public long time { get; set; } public string account { get; set; } /// /// 写 操作权限 /// public bool write { get; set; } /// /// 读取权限 /// public bool read { get; set; } } /// /// 同步模式的http服务器 /// 异步模式,处理消息是多线程 /// 同步模式,处理消息是单线程,并且需要主动调用update处理 /// public class SyncHttpServerService { private object m_locker;//锁 private HttpServer m_server; private int m_timeoutMs; //保存的外部的回调处理器 private Action m_outCallable; internal List m_requestList = new List(); List m_updateRequestList = new List(); public static Dictionary tokenList = new Dictionary(); public void StartHttpServer(int port, Route routeConfig, int timeout = 5000) { m_locker = new object();//锁 m_timeoutMs = timeout; m_outCallable = routeConfig.Callable; routeConfig.Callable = this.HttpRequestCallback; List listconfig = new List(); listconfig.Add(routeConfig); m_server = new HttpServer(port, listconfig); Thread thread = new Thread(new ThreadStart(m_server.Listen)); thread.IsBackground = true; thread.Start(); TraceLog.Debug("SyncHttpServerService StartHttpServer listen on {0}", port); } private void HttpRequestCallback(HttpContext httpContext) { DateTime beginTime = DateTime.Now; HttpRequestInfo info = new HttpRequestInfo(); info.Http = httpContext; info.BeginTime = beginTime; info.ProcessEnd = false; lock (m_locker) { m_requestList.Add(info); } bool bTimeout = false; //等待处理结束 while (true) { if (info.ProcessEnd == true) { break; } //对于http请求来说10毫秒足够了 Thread.Sleep(10); //判断超时 if ((DateTime.Now - beginTime).TotalMilliseconds >= m_timeoutMs) { TraceLog.Error("SyncHttpServerService request method {0} url {1} timeout!", httpContext.httpRequest.Method, httpContext.httpRequest.Url); bTimeout = true; break; } } lock (m_locker) { m_requestList.Remove(info); } //超时 if (bTimeout) { httpContext.httpResponse = new HttpResponse { ContentAsUTF8 = "timeout", ReasonPhrase = "InternalServerError", StatusCode = "500" }; } else { //出错,比如处理过程异常 if (info.ProcessResult != 0) { httpContext.httpResponse = new HttpResponse { ContentAsUTF8 = "error", ReasonPhrase = "InternalServerError", StatusCode = "500" }; } //成功 else { httpContext.httpResponse = info.Http.httpResponse; } } if (!httpContext.httpResponse.Headers.ContainsKey("Content-Type")) { httpContext.httpResponse.Headers["Content-Type"] = "application/json; charset=utf-8"; } HttpServer.SendResponse(httpContext); } /// /// 同步调用 /// public void Update() { DateTime beginTime = DateTime.Now; //申请一个临时数组,这样可以避免循环过程中加锁 m_updateRequestList.Clear(); lock (m_locker) { m_updateRequestList.AddRange(m_requestList); } int iCount = 0; foreach (HttpRequestInfo requestInfo in m_updateRequestList) { if (requestInfo.StartProcess == false) { requestInfo.StartProcess = true; try { m_outCallable(requestInfo.Http); //不需要等待 时退出 if (!requestInfo.Http.httpResponse.IsWaitFor) { requestInfo.ProcessEnd = true; } } catch (Exception ex) { requestInfo.ProcessEnd = true; requestInfo.ProcessResult = -1; TraceLog.Exception(ex); TraceLog.Error("SyncHttpServerService update request method {0} url {1} process error!" , requestInfo.Http.httpRequest.Method, requestInfo.Http.httpRequest.Url); } iCount++; } //一次循环最多花100毫秒时间,超过了下次tick再处理 if ((DateTime.Now - beginTime).TotalMilliseconds >= 100) { TraceLog.Error("SyncHttpServerService update process request too slow, count {0} in this update, start {1} now {2}" , iCount, beginTime.ToString("HH:mm:ss.fff"), DateTime.Now.ToString("HH:mm:ss.fff")); break; } } } } }