什么是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. flask服务器 + 协程 + 爬虫 + ui自动化

    公司有个爬取的需求,要求持续性爬取,需要永久性地挂载到目标网站上,每天爬一次里面的数据.数据有下载表格的,我通过ui自动化点击拿到数据:还有一部分数据是几乎所有的图片信息,信息量近百万,这部分用scr ...

  2. 单词检索(search)

    单词检索(search) \(Description\) 小可可是学校图书馆的管理员,现在他接手了一个十分棘手的任务. 由于学校需要一些材料,校长需要在文章中检索一些信息.校长一共给了小可可N篇文章, ...

  3. QFileDialog实现同时选择文件和文件夹,确认取消按钮英文问题解决方法

    如下图所示,需求是同时能够选择文件或者文件夹,但是QFileDialog文件窗口类要么只能选文件,要么只能选文件夹,无法同时去选择文件和文件夹: 要实现这样的需求,封装了一个类,实现同时选择文件和文件 ...

  4. SpringBoot常用注解大全

    常用注解概览 这里整理了一张SpringBoot常用注解的思维导图,本文主要讲解这些注解的用法. 组件相关注解 @ComponentScan 默认扫描当前包及其子包下面被@component,@Con ...

  5. CF1744F MEX vs MED

    个人思路: 条件可以转化成长度为 \(x\) 的区间需要包含 \([0,\lfloor \frac{(x-1)}{2} \rfloor]\). 我们从小到大枚举每一个数 \(i\),计算长度为 \(i ...

  6. PO/PI

    典型集成场景 PI总体架构 消息映射 General Concepts(通用概念) 映射编辑器 元素 分配源/目标消息类型 有3种消息类型可分配给消息映射 1.使用已经存在于IR中的对象(比如消息类型 ...

  7. CAN 接线参考

    汽车CAN总线详解 - 汽车人大空翼 - 博客园 (cnblogs.com) 汽车CAN总线 - helloWorld017 - 博客园 (cnblogs.com) CAN总线布线规范 - 不明白就去 ...

  8. 了解ASP(二)

    变量 ASP中的变量有普通变量,Session变量,Application变量. 变量的生存期 在子程序外声明的变量可被 ASP 文件中的任何脚本访问和修改. 在子程序中声明的变量只有当子程序每次执行 ...

  9. layui富文本编辑器提交时无法获取到值

    使用layui的富文本提交时一直获取不到值,仔细检查代码之后发现是没有绑定textarea,要将编辑器中的内容同步到textarea中. 先在lay-verify="名字"中输入一 ...

  10. Spring的AOP源码解析(一)

    Spring AOP 使用介绍,从前世到今生 前面写过 Spring IOC 的源码分析,很多读者希望可以出一个 Spring AOP 的源码分析,不过 Spring AOP 的源码还是比较多的,写出 ...