什么是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. JZOJ 5062. 【GDOI2017第二轮模拟day1】航海舰队

    \(\text{Solution}\) 这还是 [Lydsy2017省队十连测] 的题 不得不说 \(FFT\) 在字符串匹配中的妙啊! 前面做了道一维的题,现在这是二维的 从题目入手,不考虑可不可达 ...

  2. LeetCode算法训练-动态规划

    欢迎关注个人公众号:爱喝可可牛奶 LeetCode算法训练-动态规划 理论知识 动态规划当前状态是由前一个状态推导出来的,而贪心没有状态的转移 动态规划需要借助dp数组,可能是一维也可能是二维的 首先 ...

  3. 完全机器模拟浏览器操作自动刷网课!不怕被封!!-----python基于selenium实现超星学习通刷视频网课

    (使用过程中有小伙伴反映如果课程的第一章是空白的页面会报错,我当时做的时候是根据我自己的课程,没有第一节是空页面的现象,这个以后有时间我再改一下吧,或者小伙伴自己修改一下也可) 原谅我这个标题党,对叭 ...

  4. centOS 相关运维指令

    1.检查CPU信息: cat /proc/cpuinfo lscpu 2.top输入 top 命令,然后可以再按 m 切换显示内容 其中 KiB Mem 行为物理内存情况,单位为KB 3.free - ...

  5. sqlite查看所有表

    查询所有数据表名 SELECT name _id FROM sqlite_master WHERE type ='table'

  6. pip安装psycopg2报错Could not find a version that satisfies the requirement psycopg2

    pip安装psycopg2报错 在使用命令(pip install psycopg2)安装psycopg2时,会报错: ERROR: Could not find a version that sat ...

  7. Qt构造函数和析构函数报错undefinedreferenceto`vtable for 。。。。'

    百度了一堆,说各种的都有,无非就是说什么构造函数没有实现父类的纯虚函数,但是我明明继承并实现了,,,最后发现可能就是单纯的Qtcreater抽风了,一开始在构造里面清理了项目,发现不行. 于是一不做二 ...

  8. CVE-2023-25813 漏洞

    自己使用Nestjs 搭配 Sequelize ,在安装新包的时候提示有Critical 风险.有漏洞嘛,要第一时间处理,要处理,除了升级,还要看一下这个漏洞如何复现. 粗略得到结果如下: CVE-2 ...

  9. leecode70. 爬楼梯

    70. 爬楼梯 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n = 2 输出:2 解释:有两种方法可以爬到 ...

  10. keil调试教程

    点击跳转 如果开启调试就提示弹框错误2k,说明你没有破解你的keil,网上自行下载注册机. 调试一定要对应自己板子的晶振,否则当你测试你的延时实际时间时,keil里的sec会不一样,甚至离谱.