什么是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;
}
}
}

运用C#编写Http服务器的更多相关文章

  1. 实战WEB 服务器(JAVA编写WEB服务器)

    实战WEB 服务器(JAVA编写WEB服务器) 标签: web服务服务器javawebsockethttp服务器 2010-04-21 17:09 11631人阅读 评论(24) 收藏 举报  分类: ...

  2. 用 PHP 编写 http 服务器

    概述 众所周知,我们一般使用 PHP 开发Web程序时需要使用到比如Apache或Nginx等Web服务器来支持,那么有没有办法直接使用PHP开发HTTP服务器,答案当然是可以的,最近看了一遍Work ...

  3. 【北航软件工程】Alpha阶段前端页面编写及服务器部署

    前端页面编写 虽然之前对html语法有过一些了解,但是完全没有编写前端页面的经验,和我合作的czy大概也是这么个情况.在Alpha阶段的前端页面编写过程中,我们是摸着石头过河,html是个入门很快专精 ...

  4. Golang 编写 Tcp 服务器

    Golang 作为广泛用于服务端和云计算领域的编程语言,tcp socket 是其中至关重要的功能.无论是 WEB 服务器还是各类中间件都离不开 tcp socket 的支持. Echo 服务器 拆包 ...

  5. 使用 acl_cpp 的 HttpServlet 类及服务器框架编写WEB服务器程序(系列文章)

    在 <用C++实现类似于JAVA HttpServlet 的编程接口 > 文章中讲了如何用 HttpServlet 等相关类编写 CGI 程序,于是有网友提出了 CGI 程序低效性,不错, ...

  6. 深入学习用 Go 编写 HTTP 服务器

    Go是一门通用的编程语言,想要学习 Go 语言的 Web 开发,就必须知道如何用 Go 启动一个 HTTP 服务器用于接收和响应来自客户端的 HTTP 请求.用 Go实现一个http server非常 ...

  7. php编写tcp服务器和客户端程序

    这是我从别的地方看到的. 1.修改php.ini,打开extension=php_sockets.dll 2.客户端程序 SocketClient.php <?php set_time_limi ...

  8. JAVA编写WEB服务器

    一.超文本传输协议  1.1 HTTP请求  1.2 HTTP应答  二.Socket类  三.ServerSocket类  四.Web服务器实例  4.1 HttpServer类  4.2 Requ ...

  9. io复用select方法编写的服务器

    摘要:io多路复用是通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般都是读就绪或者写就绪),就能通知应用程序进行相应的读写操作.select函数作为io多路复用的机制,第一个参数nfds是f ...

  10. 01-简单编写http服务器

    package com.day3; import java.io.IOException; import java.io.InputStream; import java.net.ServerSock ...

随机推荐

  1. 基于FLink实现的实时安全检测(一段时间内连续登录失败20次后,下一次登录成功场景)

    研发背景 公司安全部目前针对内部系统的网络访问日志的安全审计,大部分都是T+1时效,每日当天,启动Python编写的定时任务,完成昨日的日志审计和检测,定时任务运行完成后,统一进行企业微信告警推送.这 ...

  2. 在 WXML 中使用 JS 代码

    {{}} 里面可以写任何的 JS 表达式,(一定是表达式,例如定义函数等都不属于表达式).例如,下面是在 wxml 中使用 JS 表达式: <view class="price tex ...

  3. 华为S6720S-S24S28X-A配置参数

  4. soursetree 关于https:git remote: Unauthorized和username和password修改

    一.sourcetree推送代码提交不上提示https:git remote: Unauthorized由于没有权限,需要登陆正确的账号以及密码即可以提交 二.SourceTree这是一个无效源路径/ ...

  5. ubuntu 22.04 网络配置ib网卡配置

    第一步:查看Ubuntu版本与内核版本 cat /etc/issue 这说明系统的版本为:Ubuntu 20.04.4 LTS \n \l uname -a Linux gacs-gm-11 5.4. ...

  6. UE4笔记索引

    图形 渲染 延迟渲染 三维渲染流程 渲染优化 基本渲染 材质 材质节点组合 节点分类 特别的属性 其他 坐标空间与切线空间 坐标轴 编码 平台相关 UBT编译 命令行 程序到CPU路径 C++与蓝图互 ...

  7. element ui中table动态列切换时,表格样式变形

    现象:定义多个头部和多个数据体,可以自由切换不同的头部和相应的数据体,但是切换过程表格会变形. 解决办法:table增加索引,切换头部和数据时,修改为不同的索引,即可解决 重点:表格标签上的  key ...

  8. Linux(CentOS) Mysql 8.0.30 安装(多源安装)

    Linux(CentOS) Mysql 8.0.30 安装(多源安装) 安装命令根据实际部署情况修改调整,CentOS一般选择通用版本Red Hat Enterprise Linux 7 本文档使用w ...

  9. jQuery-强大的jQuery选择器 (详解)

    jq除常用的选择写法之外的更多方法记录. 原文:jQuery-强大的jQuery选择器 (详解)[转] 1. 基础选择器 Basics 名称 说明 举例 #id 根据元素Id选择 $("di ...

  10. GIT笔记汇总

    Git的存储方式: 元空间的存储方式 SVN存储方式: 文档数据库存储类似于 K -V存储 文件版本迭代 Copy ------------------------------------------ ...