运用C#编写Http服务器

什么是HTTP服务器

Web服务器是指驻留于因特网上某种类型计算机的程序。当Web浏览器(客户端)连到服务器上并请求文件时,服务器将处理该请求并将文件反馈到该浏览器上,附带的信息会告诉浏览器如何查看该文件(即文件类型)。服务器使用HTTP(超文本传输协议)与客户机浏览器进行信息交流,这就是人们常把它们称为HTTP服务器的原因。

HTTP协议

HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。
关于HTTP协议讲解这里有一篇文章,感兴趣可以去看看 https://blog.csdn.net/gueter/article/details/1524447

代码

BaseHeader类

用于定义一些HTTP请求类和HTTP响应类的公共字段

public class BaseHeader
    {
        /// <summary>
        /// http编码格式
        /// </summary>
        public Encoding Encoding { get; set; }
        /// <summary>
        /// 报文类型
        /// </summary>
        public string Content_Type { get; set; }
        /// <summary>
        /// 报文长度
        /// </summary>
        public int Content_Length { get; set; }
        /// <summary>
        /// 报头的编码格式字段
        /// </summary>
        public string Content_Encoding { get; set; }
        /// <summary>
        /// 报文Body
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 用于存储报头的字典
        /// </summary>
        public Dictionary<string, string> Headers { get; set; }
        /// <summary>
        /// 日志单例对象  
        /// </summary>
        public static LogManager _logger = LogManager.Instance;
    }

HttpServer类

用于监听端口开启服务

public class HttpServer
    {
        /// <summary>
        /// 服务器IP
        /// </summary>
        public string ServerIP { get; private set; }

        /// <summary>
        /// 服务器端口
        /// </summary>
        public int ServerPort { get; private set; }

        /// <summary>
        /// 是否运行
        /// </summary>
        public bool IsRunning { get; private set; }

        /// <summary>
        /// 服务端Socket
        /// </summary>
        private TcpListener serverListener;

        /// <summary>
        /// 日志单例对象
        /// </summary>
        public static LogManager _logger = LogManager.Instance;

        public event Action<HttpRequest, HttpResponse> PostOps;//post事件
        public event Action<HttpRequest, HttpResponse> GetOps;//get事件

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <param name="port">端口</param>
        public HttpServer(int port)
        {
            this.ServerPort = port;
        }
        public HttpServer(string port)
        {
            this.ServerPort = Convert.ToInt32(port);
        }
        //开启服务器
        public void Start()
        {
            if (IsRunning) return;
            //创建服务端Socket
            this.serverListener = new TcpListener(IPAddress.Any, ServerPort);
            this.IsRunning = true;
            this.serverListener.Start();
            _logger.Info(string.Format("Http服务器正在监听{0}", serverListener.LocalEndpoint.ToString()));
            try
            {
                while (IsRunning)
                {
                    TcpClient client = serverListener.AcceptTcpClient();
                    Thread requestThread = new Thread(() => { ProcessRequest(client); });
                    requestThread.IsBackground = true;
                    requestThread.Start();
                }
            }
            catch
            {
                
            }
        }
        //关闭服务器
        public void Stop()
        {
            if (!IsRunning) return;
            IsRunning = false;
            serverListener.Stop();
        }

        #region 内部方法
        /// <summary>
        /// 处理客户端请求
        /// </summary>
        /// <param name="tcpClient">客户端Socket</param>
        private void ProcessRequest(TcpClient tcpClient)
        {
            //处理请求
            Stream clientStream = tcpClient.GetStream();
            Thread.Sleep(390);//不知道为什么不Sleep一下接收不到body,可以试试去掉
            if (clientStream != null)
            {
                //构造HTTP请求
                HttpRequest request = new HttpRequest(clientStream);

                //构造HTTP响应
                HttpResponse response = new HttpResponse(clientStream);

                //处理请求类型
                switch (request.Method)//根据请求方法触发不同事件
                {
                    case "GET":
                        OnGet(request, response);
                        break;
                    case "POST":
                        OnPost(request, response);
                        break;
                    default:
                        OnDefault(request, response);
                        break;
                }
            }
            
        }
        #endregion

        #region 方法
        /// <summary>
        /// 响应Get请求
        /// </summary>
        /// <param name="request">请求报文</param>
        public void OnGet(HttpRequest request, HttpResponse response)
        {
            GetOps(request, response);
        }

        /// <summary>
        /// 响应Post请求
        /// </summary>
        /// <param name="request"></param>
        public void OnPost(HttpRequest request, HttpResponse response)
        {
            PostOps(request, response);
        }

        /// <summary>
        /// 响应默认请求
        /// </summary>
        public void OnDefault(HttpRequest request, HttpResponse response)
        {

        }
        #endregion
    }

HttpRequest类

用于接收HTTP请求,并解析

public class HttpRequest : BaseHeader
    {
        #region 字段属性
        /// <summary>
        /// URL参数
        /// </summary>
        public Dictionary<string, string> Params { get; private set; }
        /// <summary>
        /// http请求方法
        /// </summary>
        public string Method { get; set; }
        /// <summary>
        /// http请求的URL地址
        /// </summary>
        public string URL { get; set; }
        /// <summary>
        /// http协议版本
        /// </summary>
        public string HTTP_Version { get; set; }
        #endregion

        /// <summary>
        /// 定义缓冲区
        /// </summary>
        private const int MAX_SIZE = 1024 * 1024 * 2; 
        private byte[] bytes = new byte[MAX_SIZE];
        private Stream DataStream;

        public HttpRequest(Stream stream)
        {
            this.DataStream = stream;
            string dataString = GetData(DataStream);
            
            var dataArray = Regex.Split(dataString, Environment.NewLine);
            var requestLine = Regex.Split(dataArray[0], @"(\s+)")
                .Where(e => e.Trim() != string.Empty)
                .ToArray();//分割出请求行的信息
            if (requestLine.Length > 0) this.Method = requestLine[0];
            if (requestLine.Length > 1) this.URL = Uri.UnescapeDataString(requestLine[1]);
            if (requestLine.Length > 2) this.HTTP_Version = requestLine[2];

            this.Headers = GetHeader(dataArray,out int index);

            if (this.Method == "POST")
            {
                this.Content_Length = Convert.ToInt32(Headers["Content-Length"]);
                if (Content_Length != 0)//数据长度不等于0
                {
                    this.Content_Type = Headers["Content-Type"];
                    this.Encoding = Content_Type.Split('=')[1] == "utf-8" ? Encoding.UTF8 : Encoding.Default;
                    this.Content = GetBody(dataArray, index);//真正的数据
                    _logger.Info("收到消息:\r\n" + Content + "\r\n");
                    //Task.Run(() =>
                    //{
                        //if (socket != null) 
                        //{
                            //byte[] buffer = this.Encoding.GetBytes(this.Content);
                            //socket.Send(buffer);
                        //}
                        //else
                        //{
                         //   _logger.Debug("上位机未连接!");
                        //}
                    //});
                }
                else
                {
                    _logger.Info("报文为空!");
                }
            }
        }

        /// <summary>
        /// 获取数据流中的数据data
        /// </summary>
        /// <param name="DataStream"></param>
        /// <returns></returns>
        public string GetData(Stream DataStream)
        {
            try
            {
                var length = 0;
                var data = string.Empty;
                do
                {
                    length = DataStream.Read(bytes, 0, MAX_SIZE - 1);
                    data += Encoding.UTF8.GetString(bytes, 0, length);
                } 
                while (length > 0 && !data.Contains("\r\n\r\n"));
                return data;
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 获取报头header
        /// </summary>
        /// <param name="dataArray"></param>
        /// <returns></returns>
        public Dictionary<string,string> GetHeader(string[] dataArray,out int index)
        {
            var header = new Dictionary<string, string>();
            index = 0;
            foreach (var item in dataArray)
            {
                index++;
                if (item == "")//读取到空行表示header已经读取完成
                {
                    return header;
                }
                if (item.Contains(':'))
                {
                    var dataTemp = item.Split(':').ToList();//把报头数据分割以键值对方式存入字典
                    if (dataTemp.Count > 2)//特殊情况Host有两个“:”
                    {
                        for (int i = 2; i < dataTemp.Count;)
                        {
                            dataTemp[1] += ":"+dataTemp[i];
                            dataTemp.Remove(dataTemp[i]);
                        }
                    }
                    header.Add(dataTemp[0].Trim(), dataTemp[1].Trim());
                }   
            }
            return header;
        }

        /// <summary>
        /// 获取报文body
        /// </summary>
        /// <param name="dataArray"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public string GetBody(string[] dataArray, int index)
        {
            string Body = string.Empty;
            for (int i = index ; i < dataArray.Length; i++) 
            {
                Body += dataArray[i];
            }
            return Body;
        }


        #region 反射
        //通过反射查找请求对应的方法(未完成)
        public void reflex()
        {
            Type t1 = this.GetType();
            //根据字符标题,取得当前函数调用
            MethodInfo method = t1.GetMethod("miaox");
            //获取需要传入的参数

            ParameterInfo[] parms = method.GetParameters();
            int haha = 1111;
            //调
            method.Invoke(this, new object[] { haha });
        }

        public void miao(int x)
        {

        }
        #endregion
    }

HttpResponse类

用于构造响应HTTP请求

public class HttpResponse : BaseHeader
    {
        #region 字段属性
        /// <summary>
        /// http协议版本
        /// </summary>
        public string HTTP_Version { get; set; }
        /// <summary>
        /// 状态码
        /// </summary>
        public string StatusCode { get; set; }
        /// <summary>
        /// http数据流
        /// </summary>
        private Stream DataStream;
        #endregion
        public HttpResponse(Stream stream)
        {
            this.DataStream = stream;
        }

        /// <summary>
        /// 构建响应头部
        /// </summary>
        /// <returns></returns>
        protected string BuildHeader()
        {
            StringBuilder builder = new StringBuilder();//StringBuilder(字符串变量)进行运算时,是一直在已有对象操作的,适合大量频繁字符串的拼接或删除
                                                        //string(字符串常量)在进行运算的时候是重新生成了一个新的string对象,不适合大量频繁字符串的拼接或删除

            if (!string.IsNullOrEmpty(StatusCode))
                builder.Append(HTTP_Version + " " + StatusCode + "\r\n");

            if (!string.IsNullOrEmpty(this.Content_Type))
                builder.AppendLine("Content-Type:" + this.Content_Type);
            return builder.ToString();
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        public void Send()
        {
            if (!DataStream.CanWrite) return;
            try
            {
                //发送响应头
                var header = BuildHeader();
                byte[] headerBytes = this.Encoding.GetBytes(header);
                DataStream.Write(headerBytes, 0, headerBytes.Length);

                //发送空行
                byte[] lineBytes = this.Encoding.GetBytes(System.Environment.NewLine);
                DataStream.Write(lineBytes, 0, lineBytes.Length);

                //发送内容
                byte[] buffer = this.Encoding.GetBytes(this.Content);
                DataStream.Write(buffer, 0, buffer.Length);
            }
            catch(Exception e)
            {
                _logger.Debug("服务器响应异常!" + e.Message);
            }
            finally
            {
                DataStream.Close();
            }
        }
    }

调用

#region...日志...
/// <summary>
/// 日志单例对象
/// </summary>
public static LogManager _logger = LogManager.Instance;

/// <summary>
/// 写入日志框
/// </summary>
/// <param name="obj">日志对象</param>
private void LogManager_Event(LogInfo obj)
{
log_txt.Font = new Font("黑体", 8, FontStyle.Regular);
//若是超过N行 则清除
if (log_txt.Lines.Length > 500)
{
log_txt.Clear();
log_txt.AppendText("更多日志,请到日志文件中查看。\r\n");
}
if (obj.LogLevel == LogLevel.Info)
{
log_txt.SelectionColor = Color.DarkBlue;
}
if (obj.LogLevel == LogLevel.Error)
{
log_txt.SelectionColor = Color.Red;
}
if (obj.LogLevel == LogLevel.Debug)
{
log_txt.SelectionColor = Color.Orange;
}
if (obj.LogLevel == LogLevel.Fatal)
{
//this._textBox.SelectionColor = Color.Red;
log_txt.SelectionColor = Color.Purple;
}
log_txt.AppendText(obj.Message + "\r\n");
log_txt.ScrollToCaret();
}

/// <summary>
/// 初始化日志
/// </summary>
private void LogInit()
{
LogManager.Event += LogManager_Event;
}
#endregion

private void Form1_Load(object sender, EventArgs e)
{
HttpPort_txt.Text = MsgList[0];

LogInit();
_logger.Info("日志初始化...\r\n");

Control.CheckForIllegalCrossThreadCalls = false;

httpServer = new HttpServer(HttpPort_txt.Text);
httpServer.GetOps += HttpServer_GetOps;
httpServer.PostOps += HttpServer_PostOps;
Task.Run(new Action(() => { httpServer.Start(); }));

_logger.Info("服务器正在开启,请稍等...");

}

日志类LogManager

用于显示日志信息和生成日志文件

/// <summary>
    /// 日志级别
    /// </summary>
    public enum LogLevel
    {
        /// <summary>
        /// 信息级别
        /// </summary>
        Info,

        /// <summary>
        /// debug级别
        /// </summary>
        Debug,

        /// <summary>
        /// 错误级别
        /// </summary>
        Error,

        /// <summary>
        /// 致命级别
        /// </summary>
        Fatal
    }

    /// <summary>
    /// 日志信息
    /// </summary>
    public class LogInfo
    {
        /// <summary>
        /// 时间
        /// </summary>
        public DateTime Time { get; set; }

        /// <summary>
        /// 线程id
        /// </summary>
        public int ThreadId { get; set; }

        /// <summary>
        /// 日志级别
        /// </summary>
        public LogLevel LogLevel { get; set; }

        /// <summary>
        /// 异常源
        /// </summary>
        public string Source { get; set; }

        /// <summary>
        /// 异常信息
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// 异常对象
        /// </summary>
        public Exception Exception { get; set; }

        /// <summary>
        /// 日志类型
        /// </summary>
        public string ExceptionType { get; set; }

        /// <summary>
        /// 请求路径
        /// </summary>
        public string RequestUrl { get; set; }

        /// <summary>
        /// 客户端代理
        /// </summary>
        public string UserAgent { get; set; }
    }

    /// <summary>
    /// 日志组件
    /// </summary>
    public class LogManager
    {
        /// <summary>
        /// 日志对象单例
        /// </summary>
        static volatile LogManager _instance;
        static object _lock = new object();//双重验证锁

        /// <summary>
        /// 获取日志对象的单例
        /// </summary>
        public static LogManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new LogManager();
                        }
                    }
                }
                return _instance;
            }
        }

        static ConcurrentQueue<Tuple<string, string>> LogQueue = new ConcurrentQueue<Tuple<string, string>>();

        /// <summary>
        /// 自定义事件
        /// </summary>
        public static event Action<LogInfo> Event;

        static DateTime _now
        {
            get { return DateTime.Now; }
        }//日志记录时间

        private LogManager()
        {
            var writeTask = new Task((obj) =>
            {
                while (true)
                {
                    Pause.WaitOne(1000, true);
                    List<string[]> temp = new List<string[]>();
                    Tuple<string, string> logItem;
                    LogQueue.TryDequeue(out logItem);
                    if (logItem != null)
                    {
                        string logPath = logItem.Item1;
                        string logMergeContent = string.Concat(logItem.Item2, "----------------------------------------------------------------------------------------------------------------------\r\n");
                        string[] logArr = temp.FirstOrDefault(d => d[0].Equals(logPath));
                        if (logArr != null)
                        {
                            logArr[1] = string.Concat(logArr[1], logMergeContent);
                        }
                        else
                        {
                            logArr = new[]
                            {
                                logPath,
                                logMergeContent
                                };
                            temp.Add(logArr);

                            foreach (var item in temp)
                            {
                                WriteText(item[0], item[1]);
                            }
                        }
                    }

                }
            }, null, TaskCreationOptions.LongRunning);

            writeTask.Start();
        }

        private static AutoResetEvent Pause => new AutoResetEvent(false);

        /// <summary>
        /// 日志存放目录,默认日志放在当前应用程序运行目录下的logs文件夹中
        /// </summary>
        public static string LogDirectory
        {
            get { return Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Any(s => s.Contains("Web.config")) ? AppDomain.CurrentDomain.BaseDirectory + @"App_Data\Logs\" : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"); }
            set
            {
            }
        }

        /// <summary>
        /// 写入Info级别的日志
        /// </summary>
        /// <param name="info"></param>
        public void Info(string info)
        {

            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(info).ToUpper()}\r\n日志消息:{info}\r\n"));
            var log = new LogInfo()
            {
                LogLevel = LogLevel.Info,
                Message = info,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入Info级别的日志
        /// </summary>
        /// <param name="source"></param>
        /// <param name="info"></param>
        public void Info(string source, string info)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(info).ToUpper()}\r\n日志资源:{source}\r\n日志消息:{info}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Info,
                Message = info,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入Info级别的日志
        /// </summary>
        /// <param name="source"></param>
        /// <param name="info"></param>
        public void Info(Type source, string info)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(info).ToUpper()}\r\n日志资源名:{source.FullName}\r\n日志消息:{info}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Info,
                Message = info,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source.FullName
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入debug级别日志
        /// </summary>
        /// <param name="debug">异常对象</param>
        public void Debug(string debug)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(debug).ToUpper()}\r\n日志消息:{debug}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Debug,
                Message = debug,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入debug级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="debug">异常对象</param>
        public void Debug(string source, string debug)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(debug).ToUpper()}\r\n日志资源:{source}\r\n日志消息:{debug}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Debug,
                Message = debug,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入debug级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="debug">异常对象</param>
        public void Debug(Type source, string debug)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(debug).ToUpper()}\r\n日志资源:{source.FullName}\r\n日志消息:{debug}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Debug,
                Message = debug,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source.FullName
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入error级别日志
        /// </summary>
        /// <param name="error">异常对象</param>
        public void Error(Exception error)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(error).ToUpper()}\r\n日志资源:{error.Source}\r\n日志消息:{error.Message}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Error,
                Message = error.Message,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = error.Source,
                Exception = error,
                ExceptionType = error.GetType().Name
            };
            Event?.Invoke(log);
        }

        public void Error(string error)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(error).ToUpper()}\r\n日志消息:{error}\r\n"));
            var log = new LogInfo()
            {
                LogLevel = LogLevel.Error,
                Message = error,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入error级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="error">异常对象</param>
        public void Error(Type source, Exception error)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(error).ToUpper()}\r\n日志资源:{source.FullName}\r\n日志消息:{error.Message}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Error,
                Message = error.Message,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source.FullName,
                Exception = error,
                ExceptionType = error.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入error级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="error">异常信息</param>
        public void Error(Type source, string error)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(error).ToUpper()}\r\n日志资源:{source.FullName}\r\n日志消息:{error}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Error,
                Message = error,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source.FullName,
                //Exception = error,
                ExceptionType = error.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入error级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="error">异常对象</param>
        public void Error(string source, Exception error)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(error).ToUpper()}\r\n日志资源:{source}\r\n日志消息:{error.Message}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Error,
                Message = error.Message,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source,
                Exception = error,
                ExceptionType = error.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入error级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="error">异常信息</param>
        public void Error(string source, string error)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(error).ToUpper()}\r\n日志资源:{source}\r\n日志消息:{error}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Error,
                Message = error,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source,
                //Exception = error,
                ExceptionType = error.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入fatal级别日志
        /// </summary>
        /// <param name="fatal">异常对象</param>
        public void Fatal(Exception fatal)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(fatal).ToUpper()}\r\n日志资源:{fatal.Source}\r\n日志消息:{fatal.Message}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Fatal,
                Message = fatal.Message,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = fatal.Source,
                Exception = fatal,
                ExceptionType = fatal.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入fatal级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="fatal">异常对象</param>
        public void Fatal(Type source, Exception fatal)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间: {_now} \r\n线程ID:[ {Thread.CurrentThread.ManagedThreadId} ]\r\n日志级别: {nameof(fatal).ToUpper()} \r\n日志资源: {source.FullName} \r\n日志消息: {fatal.Message} \r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Fatal,
                Message = fatal.Message,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source.FullName,
                Exception = fatal,
                ExceptionType = fatal.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入fatal级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="fatal">异常对象</param>
        public void Fatal(Type source, string fatal)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间: {_now} \r\n线程ID:[ {Thread.CurrentThread.ManagedThreadId} ]\r\n日志级别: {nameof(fatal).ToUpper()} \r\n日志资源: {source.FullName} \r\n日志消息: {fatal} \r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Fatal,
                Message = fatal,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source.FullName,
                //Exception = fatal,
                ExceptionType = fatal.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入fatal级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="fatal">异常对象</param>
        public void Fatal(string source, Exception fatal)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间:{_now}\r\n线程ID:[{Thread.CurrentThread.ManagedThreadId}]\r\n日志级别:{nameof(fatal).ToUpper()}\r\n日志资源:{source}\r\n日志消息:{fatal.Message}\r\n"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Fatal,
                Message = fatal.Message,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source,
                Exception = fatal,
                ExceptionType = fatal.GetType().Name
            };
            Event?.Invoke(log);
        }

        /// <summary>
        /// 写入fatal级别日志
        /// </summary>
        /// <param name="source">异常源的类型</param>
        /// <param name="fatal">异常对象</param>
        public void Fatal(string source, string fatal)
        {
            LogQueue.Enqueue(new Tuple<string, string>(GetLogPath(), $"时间: {_now} \r\n线程ID:[ {Thread.CurrentThread.ManagedThreadId} ]\r\n日志级别: {nameof(fatal).ToUpper()} \r\n日志资源: {source} \r\n日志消息:{fatal}"));
            LogInfo log = new LogInfo()
            {
                LogLevel = LogLevel.Fatal,
                Message = fatal,
                Time = _now,
                ThreadId = Thread.CurrentThread.ManagedThreadId,
                Source = source,
                ExceptionType = fatal.GetType().Name
            };
            Event?.Invoke(log);
        }

        private string GetLogPath()
        {
            string newFilePath;
            String logDir = string.IsNullOrEmpty(LogDirectory) ? Path.Combine(Environment.CurrentDirectory, "logs") : LogDirectory;
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }

            string extension = ".log";
            string fileNameNotExt = _now.ToString("yyyyMMdd");
            string fileNamePattern = string.Concat(fileNameNotExt, "(*)", extension);
            List<string> filePaths = Directory.GetFiles(logDir, fileNamePattern, SearchOption.TopDirectoryOnly).ToList();

            if (filePaths.Count > 0)
            {
                int fileMaxLen = filePaths.Max(d => d.Length);
                string lastFilePath = filePaths.Where(d => d.Length == fileMaxLen).OrderByDescending(d => d).FirstOrDefault();
                if (new FileInfo(lastFilePath).Length > 1 * 1024 * 1024)
                {
                    string no = new Regex(@"(?is)(?<=\()(.*)(?=\))").Match(Path.GetFileName(lastFilePath)).Value;
                    Int32 tempno;
                    bool parse = int.TryParse(no, out tempno);
                    string formatno = $"({(parse ? (tempno + 1) : tempno)})";
                    string newFileName = String.Concat(fileNameNotExt, formatno, extension);
                    newFilePath = Path.Combine(logDir, newFileName);
                }
                else
                {
                    newFilePath = lastFilePath;
                }
            }
            else
            {
                string newFileName = string.Concat(fileNameNotExt, $"({0})", extension);
                newFilePath = Path.Combine(logDir, newFileName);
            }

            return newFilePath;
        }

        private void WriteText(string logPath, string logContent)
        {
            try
            {
                if (!File.Exists(logPath))
                {
                    File.CreateText(logPath).Close();
                }

                using (StreamWriter sw = File.AppendText(logPath))
                {
                    sw.Write(logContent);
                }

            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

 

posted on 2023-01-13 16:36  othersheart  阅读(5197)  评论(0编辑  收藏  举报