UdpServer

Udp服务端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using Notify.Log;namespace UdpSer
{public class UdpServer{// 创建UDP端点,并绑定到本地端口IPEndPoint localEndPoint;// 创建UDP套接字private UdpClient udpServer = new UdpClient();private volatile bool runing = false;private byte[] receiveBytes = new byte[2048];private byte[] sendBytes = new byte[2048];private Queue<LogContentV2> logBuffer = new Queue<LogContentV2>();private Thread listenThread;public int LogBufferCount { get { return this.logBuffer.Count; } }public LogContentV2 Log { get { return this.logBuffer.Dequeue(); } }public UdpServer(){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, 8421);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer default constructed."));}public UdpServer(int port = 8421){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, port);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer constructed."));}public void Startup(){this.localEndPoint = new IPEndPoint(IPAddress.Any, 8421);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(int port){this.localEndPoint = new IPEndPoint(IPAddress.Any, port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(string ipaddr, int port){this.localEndPoint = new IPEndPoint(IPAddress.Parse(ipaddr), port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Stop(){try{this.runing = false;switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:Thread.Sleep(2000); // 让线程工作一段时间break;case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();break;case System.Threading.ThreadState.Background:case System.Threading.ThreadState.Running:this.listenThread.Join();break;}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stop Called."));}catch (Exception e){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "UdpServer Stop Exception.", e));}System.GC.Collect();logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stoped Called System.GC.Collect."));}private void TaskRunning(){Task.Run(() =>{try{while (runing){// 接收数据this.receiveBytes = udpServer.Receive(ref localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Received {receiveBytes.Length} Bytes."));//处理数据HandleReceiveResposoneModel();// 响应数据if (sendBytes.Length > 0){udpServer.Send(sendBytes, sendBytes.Length, localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Sented {receiveBytes.Length} Bytes."));}}}catch (Exception e){Console.WriteLine(e.ToString());logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "Task.Run Receive Exception.", e));}});}private void HandleReceiveResposoneModel(){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"HandleReceiveResposoneModel"));//this.receiveBytes;//this.sendBytes;string sendMessage = "Message received";sendBytes = Encoding.UTF8.GetBytes(sendMessage);}}internal class Program{static void Main(string[] args){UdpServer udpServer = new UdpServer();udpServer.Startup("127.0.0.1",8421);Console.WriteLine("Press any key to stop the server");Console.ReadKey();udpServer.Stop();}}
}
namespace Notify.Log
{public enum LogLevel{Trace = 0,Debug = 1,Information = 2,Statistic = 3,Warning = 4,Mistake = 6,    //轻微错误Exception = 5,Error = 7,      //逻辑错误Critical = 8,    //严重错误Fault = 9       //致命错误}public enum LogLevelV2{Infor = 2,Excep = 5,Error = 7,}//临时日志是写文本文件,这种操作在高并发程序里会造成程序崩溃public class TempLog{//注意只有一个线程写,不能多个线程同时写文件。static public void logging(List<NtLog> logbuf, string filepath = "./NotifyLog.log"){// 确保日志文件的目录存在  Directory.CreateDirectory(Path.GetDirectoryName(filepath));// 使用StreamWriter写入日志  using (StreamWriter writer = new StreamWriter(filepath, true)) // true表示追加模式  {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{//    writer.WriteLine(log.ToString());//    移除已经写了的缓存//    logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){//#if DEBUG//                    Console.WriteLine(logbuf[i].ToString());//#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(List<NtLog> logbuf){string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log"  string fullPath = Path.Combine("./logs", fileName);// 确保日志文件的目录存在  Directory.CreateDirectory(Path.GetDirectoryName(fullPath));// 使用StreamWriter写入日志  using (StreamWriter writer = new StreamWriter(fullPath, true)) // true表示追加模式  {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{//    writer.WriteLine(log.ToString());//    移除已经写了的缓存//    logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){
#if DEBUGConsole.WriteLine(logbuf[i].ToString());
#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(string message, string logpath){using (StreamWriter writer = new StreamWriter(logpath, true)) // true表示追加模式  {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log"  string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}static public void logging(string message){string path = AppDomain.CurrentDomain.BaseDirectory;using (StreamWriter writer = new StreamWriter(path + "//TempLog.log", true)) // true表示追加模式  {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log"  string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}}public class LogContentV2{public DateTime Occurrence { get; set; }public LogLevelV2 LevelV2 { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentV2() { }public LogContentV2(LogLevelV2 level, string message){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContentV2(LogLevelV2 level, string message, Exception e){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.ffff")} {LevelV2.ToString()}:{Message}";//因为ffff会确保输出始终是4位数字,不足的部分用零填充。}}public class LogContent{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContent() { }public LogContent(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContent(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){//string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";//string tmp = $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()} {Message}";//return tmp;return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()}:{Message}";}}public class LogContentX{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentX() { }public LogContentX(LogLevel level, string message) { this.SetLog(level, message); }public LogContentX(LogLevel level, string message, Exception e) { this.SetLog(level, message, e); }public void SetLog(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public void SetLog(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";return tmp;}public string TraceDetail(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";tmp += this.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public static string TraceDetail(LogContent log){string tmp = log.Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + " " + log.Level.ToString() + ":" + log.Message + "\n";tmp += log.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public string TraceTopFrame(){return this.Trace.GetFrame(0).ToString();}public StackFrame TraceTopStackFrame(){return Trace.GetFrame(0);}public StackFrame TraceBottomStackFrame(){return Trace.GetFrame(this.Trace.FrameCount - 1);}public int GetSize(){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + this.Message.Length * 2 + 8;for (int i = 0; i < this.Trace.FrameCount; i++){StackFrame sf = this.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}public static int GetSize(LogContent log){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + log.Message.Length * 2 + 8;for (int i = 0; i < log.Trace.FrameCount; i++){StackFrame sf = log.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}}public class LogBuffer{protected List<LogContent> buf = new List<LogContent>();public List<LogContent> Buffer { get { return buf; } }public LogBuffer(){buf = new List<LogContent>();}public LogBuffer(List<LogContent> buf){this.buf = buf;}public void Insert(LogContent log){this.buf.Add(log);}public void Insert(LogBuffer log){foreach (var item in log.Buffer){this.buf.Add(item);}}public int LogSize(){int size = 0;foreach (LogContent cnt in this.buf){size += LogContentX.GetSize(cnt);}return size;}}public class LogBufQuery{public List<LogContent> Buffer { get; set; }public void TimeOrderAsc(){Buffer.Sort((x, y) => x.Occurrence.CompareTo(y.Occurrence));}public void TimeOrderDsc(){Buffer.Sort((x, y) => y.Occurrence.CompareTo(x.Occurrence));}public List<LogContent> FilterByLoglevel(LogLevel loglevel){return Buffer.FindAll(log => log.Level == loglevel);}}public struct logstatics{public string item;public string value;public long Timestamp;// 将 UNIX 时间戳转换为 DateTime//DateTime dateTime = DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;public DateTime FromUnixTime(){return DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;}}public class TotalAccessSattistic{private ulong totalAccess;/// <summary>/// 总访问量/// </summary>public ulong TotalAccess{get{return this.totalAccess;}}private void Reset(){ this.totalAccess = 0; }public void StasticAccess(List<LogContent> buf, string flagstr = "HandleClientComm"){foreach (var cnt in buf){if (cnt.Message == flagstr)this.totalAccess++;}}}//将日志写成文本文件,注意在多线程环境下要排除线程互斥。public class NtLog{//private Queue<LogBuffer> Buff = new Queue<LogBuffer>();private Queue<LogContent> buffer = new Queue<LogContent>();public string LogPath { get; }private string curfilepath = string.Empty;private string errorLgFile = string.Empty;  //定义从Exception到Fault这5个层级为Errorprivate Task task;  //不要删除,多线程写日志时会用到private Stopwatch watcher = new Stopwatch();private long maxms, minms, lastms;private volatile bool IsWriting = false;public bool Writing { get { return IsWriting; } }/// <summary>/// 平均耗时/// </summary>public long AverageConsum{get{return (maxms + minms + lastms) / 3;}}public NtLog(){this.LogPath = AppDomain.CurrentDomain.BaseDirectory;创建日志文件夹this.LogPath = CreateLogDirectory();MakeLogFileName();maxms = minms = lastms = 0;}public void Enqueue(LogContent log){this.buffer.Enqueue(log);}public void Enqueue(List<LogContent> logs){foreach (LogContent log in logs){this.buffer.Enqueue(log);}}public void Enqueue(LogBuffer logbuf){foreach (LogContent log in logbuf.Buffer){this.buffer.Enqueue(log);}}public void OnLogging(List<LogContent> logs){//#if DEBUG//            TempLog.logging($"查看原始数据。{logs.Count} ");//{logs.First().Message}//#endif//this.Buff.Enqueue(new LogBuffer(logs));this.Enqueue(logs);this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{//    Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public void OnLogging(Queue<LogContent> logs){for (int i = 0; i < logs.Count; i++){this.buffer.Enqueue(logs.Dequeue());}this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{//    Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public static string CreateLogDirectory(){string path = AppDomain.CurrentDomain.BaseDirectory;// 获取当前应用程序域的名称(通常是程序集名称)string assemblyName = AppDomain.CurrentDomain.FriendlyName;// 去掉路径和扩展名,只保留文件名assemblyName = Path.GetFileNameWithoutExtension(assemblyName);// 组合成完整的路径path = System.IO.Path.Combine(path, assemblyName + "Log");//TempLog.logging(path);//创建日志文件夹Directory.CreateDirectory(path);return path;}public void UpdatePathFileName(){string path = AppDomain.CurrentDomain.BaseDirectory;// 获取当前应用程序域的名称(通常是程序集名称)string assemblyName = AppDomain.CurrentDomain.FriendlyName;// 去掉路径和扩展名,只保留文件名assemblyName = Path.GetFileNameWithoutExtension(assemblyName);// 组合成完整的路径path = System.IO.Path.Combine(path, assemblyName + "Log");//TempLog.logging(path);//创建日志文件夹Directory.CreateDirectory(path);string dn = DateTime.Now.ToString("yyyy-MM-dd");this.curfilepath = Path.Combine(this.LogPath, assemblyName + dn + ".log");this.errorLgFile = Path.Combine(this.LogPath, assemblyName + dn + "err.log");}public void MakeLogFileName(){// 获取当前应用程序域的名称(通常是程序集名称)string assemblyName = AppDomain.CurrentDomain.FriendlyName;// 去掉路径和扩展名,只保留文件名assemblyName = Path.GetFileNameWithoutExtension(assemblyName);string dn = DateTime.Now.ToString("yyyy-MM-dd");this.curfilepath = Path.Combine(this.LogPath, assemblyName + dn + ".log");this.errorLgFile = Path.Combine(this.LogPath, assemblyName + dn + "err.log");}public void WriteLogFile(){using (StreamWriter writer = new StreamWriter(this.curfilepath, true)) // true表示追加模式  {foreach (var cnt in this.buffer){writer.WriteLine(cnt.ToString());}}}public void WriteErrorLog(){using (StreamWriter writer = new StreamWriter(this.errorLgFile, true)) // true表示追加模式  {foreach (var cnt in this.buffer){if (cnt.Level >= LogLevel.Warning)writer.WriteLine(LogContentX.TraceDetail(cnt));}}}//发现它仍然阻塞主线程//注意只有一个线程写,不能多个线程同时写文件。//请注意,Buffer.Remove(cnt) 在循环中可能会导致问题,因为从集合中移除元素会改变集合的大小,从而可能导致迭代器失效。为了避免这个问题,可以先收集需要删除的元素,然后在循环结束后统一删除它们。public void WriteLogByThread(LogBuffer logs){this.watcher.Start();this.IsWriting = true;//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None),fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1), writer2 = new StreamWriter(fs2)){foreach (var cnt in logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)writer2.WriteLine(LogContentX.TraceDetail(cnt));}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}//如果没有errlog就不写public void WriteLogByThreadV2(LogBuffer logs){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1)){foreach (var cnt in logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)errlogs.Enqueue(cnt);}}}if (errlogs.Count > 0){using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer2 = new StreamWriter(fs2)){for (int i = 0; i < errlogs.Count; i++){writer2.WriteLine(errlogs.Dequeue().ToString());}}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}public void WriteLogByThreadV3(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1)){//foreach (var cnt in queue)//{//    writer.WriteLine(cnt.ToString());//    ;//    if (cnt.Level >= LogLevel.Warning)//        errlogs.Enqueue(cnt);//}while (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}if (errlogs.Count > 0){using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer2 = new StreamWriter(fs2)){for (int i = 0; i < errlogs.Count; i++){writer2.WriteLine(errlogs.Dequeue().ToString());}}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}public void WriteLogByThreadV4(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1)){//foreach (var cnt in queue)//{//    writer.WriteLine(cnt.ToString());//    ;//    if (cnt.Level >= LogLevel.Warning)//        errlogs.Enqueue(cnt);//}while (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}if (errlogs.Count > 0){using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer2 = new StreamWriter(fs2)){for (int i = 0; i < errlogs.Count; i++){writer2.WriteLine(LogContentX.TraceDetail(errlogs.Dequeue()));}}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}}
}

Udp客户端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using Notify.Log;namespace UdpSer
{public class UdpServer{// 创建UDP端点,并绑定到本地端口IPEndPoint localEndPoint;// 创建UDP套接字private UdpClient udpServer = new UdpClient();private volatile bool runing = false;private byte[] receiveBytes = new byte[2048];private byte[] sendBytes = new byte[2048];private Queue<LogContentV2> logBuffer = new Queue<LogContentV2>();private Thread listenThread;public int LogBufferCount { get { return this.logBuffer.Count; } }public LogContentV2 Log { get { return this.logBuffer.Dequeue(); } }public UdpServer(){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, 8421);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer default constructed."));}public UdpServer(int port = 8421){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, port);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer constructed."));}public void Startup(){this.localEndPoint = new IPEndPoint(IPAddress.Any, 8421);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(int port){this.localEndPoint = new IPEndPoint(IPAddress.Any, port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(string ipaddr, int port){this.localEndPoint = new IPEndPoint(IPAddress.Parse(ipaddr), port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Stop(){try{this.runing = false;switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:Thread.Sleep(2000); // 让线程工作一段时间break;case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();break;case System.Threading.ThreadState.Background:case System.Threading.ThreadState.Running:this.listenThread.Join();break;}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stop Called."));}catch (Exception e){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "UdpServer Stop Exception.", e));}System.GC.Collect();logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stoped Called System.GC.Collect."));}private void TaskRunning(){Task.Run(() =>{try{while (runing){// 接收数据this.receiveBytes = udpServer.Receive(ref localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Received {receiveBytes.Length} Bytes."));//处理数据HandleReceiveResposoneModel();// 响应数据if (sendBytes.Length > 0){udpServer.Send(sendBytes, sendBytes.Length, localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Sented {receiveBytes.Length} Bytes."));}}}catch (Exception e){Console.WriteLine(e.ToString());logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "Task.Run Receive Exception.", e));}});}private void HandleReceiveResposoneModel(){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"HandleReceiveResposoneModel"));//this.receiveBytes;//this.sendBytes;string sendMessage = "Message received";sendBytes = Encoding.UTF8.GetBytes(sendMessage);}}internal class Program{static void Main(string[] args){UdpServer udpServer = new UdpServer();udpServer.Startup("127.0.0.1",8421);Console.WriteLine("Press any key to stop the server");Console.ReadKey();udpServer.Stop();}}
}
namespace Notify.Log
{public enum LogLevel{Trace = 0,Debug = 1,Information = 2,Statistic = 3,Warning = 4,Mistake = 6,    //轻微错误Exception = 5,Error = 7,      //逻辑错误Critical = 8,    //严重错误Fault = 9       //致命错误}public enum LogLevelV2{Infor = 2,Excep = 5,Error = 7,}//临时日志是写文本文件,这种操作在高并发程序里会造成程序崩溃public class TempLog{//注意只有一个线程写,不能多个线程同时写文件。static public void logging(List<NtLog> logbuf, string filepath = "./NotifyLog.log"){// 确保日志文件的目录存在  Directory.CreateDirectory(Path.GetDirectoryName(filepath));// 使用StreamWriter写入日志  using (StreamWriter writer = new StreamWriter(filepath, true)) // true表示追加模式  {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{//    writer.WriteLine(log.ToString());//    移除已经写了的缓存//    logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){//#if DEBUG//                    Console.WriteLine(logbuf[i].ToString());//#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(List<NtLog> logbuf){string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log"  string fullPath = Path.Combine("./logs", fileName);// 确保日志文件的目录存在  Directory.CreateDirectory(Path.GetDirectoryName(fullPath));// 使用StreamWriter写入日志  using (StreamWriter writer = new StreamWriter(fullPath, true)) // true表示追加模式  {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{//    writer.WriteLine(log.ToString());//    移除已经写了的缓存//    logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){
#if DEBUGConsole.WriteLine(logbuf[i].ToString());
#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(string message, string logpath){using (StreamWriter writer = new StreamWriter(logpath, true)) // true表示追加模式  {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log"  string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}static public void logging(string message){string path = AppDomain.CurrentDomain.BaseDirectory;using (StreamWriter writer = new StreamWriter(path + "//TempLog.log", true)) // true表示追加模式  {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log"  string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}}public class LogContentV2{public DateTime Occurrence { get; set; }public LogLevelV2 LevelV2 { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentV2() { }public LogContentV2(LogLevelV2 level, string message){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContentV2(LogLevelV2 level, string message, Exception e){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.ffff")} {LevelV2.ToString()}:{Message}";//因为ffff会确保输出始终是4位数字,不足的部分用零填充。}}public class LogContent{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContent() { }public LogContent(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContent(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){//string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";//string tmp = $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()} {Message}";//return tmp;return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()}:{Message}";}}public class LogContentX{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentX() { }public LogContentX(LogLevel level, string message) { this.SetLog(level, message); }public LogContentX(LogLevel level, string message, Exception e) { this.SetLog(level, message, e); }public void SetLog(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public void SetLog(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";return tmp;}public string TraceDetail(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";tmp += this.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public static string TraceDetail(LogContent log){string tmp = log.Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + " " + log.Level.ToString() + ":" + log.Message + "\n";tmp += log.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public string TraceTopFrame(){return this.Trace.GetFrame(0).ToString();}public StackFrame TraceTopStackFrame(){return Trace.GetFrame(0);}public StackFrame TraceBottomStackFrame(){return Trace.GetFrame(this.Trace.FrameCount - 1);}public int GetSize(){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + this.Message.Length * 2 + 8;for (int i = 0; i < this.Trace.FrameCount; i++){StackFrame sf = this.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}public static int GetSize(LogContent log){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + log.Message.Length * 2 + 8;for (int i = 0; i < log.Trace.FrameCount; i++){StackFrame sf = log.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}}public class LogBuffer{protected List<LogContent> buf = new List<LogContent>();public List<LogContent> Buffer { get { return buf; } }public LogBuffer(){buf = new List<LogContent>();}public LogBuffer(List<LogContent> buf){this.buf = buf;}public void Insert(LogContent log){this.buf.Add(log);}public void Insert(LogBuffer log){foreach (var item in log.Buffer){this.buf.Add(item);}}public int LogSize(){int size = 0;foreach (LogContent cnt in this.buf){size += LogContentX.GetSize(cnt);}return size;}}public class LogBufQuery{public List<LogContent> Buffer { get; set; }public void TimeOrderAsc(){Buffer.Sort((x, y) => x.Occurrence.CompareTo(y.Occurrence));}public void TimeOrderDsc(){Buffer.Sort((x, y) => y.Occurrence.CompareTo(x.Occurrence));}public List<LogContent> FilterByLoglevel(LogLevel loglevel){return Buffer.FindAll(log => log.Level == loglevel);}}public struct logstatics{public string item;public string value;public long Timestamp;// 将 UNIX 时间戳转换为 DateTime//DateTime dateTime = DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;public DateTime FromUnixTime(){return DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;}}public class TotalAccessSattistic{private ulong totalAccess;/// <summary>/// 总访问量/// </summary>public ulong TotalAccess{get{return this.totalAccess;}}private void Reset(){ this.totalAccess = 0; }public void StasticAccess(List<LogContent> buf, string flagstr = "HandleClientComm"){foreach (var cnt in buf){if (cnt.Message == flagstr)this.totalAccess++;}}}//将日志写成文本文件,注意在多线程环境下要排除线程互斥。public class NtLog{//private Queue<LogBuffer> Buff = new Queue<LogBuffer>();private Queue<LogContent> buffer = new Queue<LogContent>();public string LogPath { get; }private string curfilepath = string.Empty;private string errorLgFile = string.Empty;  //定义从Exception到Fault这5个层级为Errorprivate Task task;  //不要删除,多线程写日志时会用到private Stopwatch watcher = new Stopwatch();private long maxms, minms, lastms;private volatile bool IsWriting = false;public bool Writing { get { return IsWriting; } }/// <summary>/// 平均耗时/// </summary>public long AverageConsum{get{return (maxms + minms + lastms) / 3;}}public NtLog(){this.LogPath = AppDomain.CurrentDomain.BaseDirectory;创建日志文件夹this.LogPath = CreateLogDirectory();MakeLogFileName();maxms = minms = lastms = 0;}public void Enqueue(LogContent log){this.buffer.Enqueue(log);}public void Enqueue(List<LogContent> logs){foreach (LogContent log in logs){this.buffer.Enqueue(log);}}public void Enqueue(LogBuffer logbuf){foreach (LogContent log in logbuf.Buffer){this.buffer.Enqueue(log);}}public void OnLogging(List<LogContent> logs){//#if DEBUG//            TempLog.logging($"查看原始数据。{logs.Count} ");//{logs.First().Message}//#endif//this.Buff.Enqueue(new LogBuffer(logs));this.Enqueue(logs);this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{//    Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public void OnLogging(Queue<LogContent> logs){for (int i = 0; i < logs.Count; i++){this.buffer.Enqueue(logs.Dequeue());}this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{//    Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public static string CreateLogDirectory(){string path = AppDomain.CurrentDomain.BaseDirectory;// 获取当前应用程序域的名称(通常是程序集名称)string assemblyName = AppDomain.CurrentDomain.FriendlyName;// 去掉路径和扩展名,只保留文件名assemblyName = Path.GetFileNameWithoutExtension(assemblyName);// 组合成完整的路径path = System.IO.Path.Combine(path, assemblyName + "Log");//TempLog.logging(path);//创建日志文件夹Directory.CreateDirectory(path);return path;}public void UpdatePathFileName(){string path = AppDomain.CurrentDomain.BaseDirectory;// 获取当前应用程序域的名称(通常是程序集名称)string assemblyName = AppDomain.CurrentDomain.FriendlyName;// 去掉路径和扩展名,只保留文件名assemblyName = Path.GetFileNameWithoutExtension(assemblyName);// 组合成完整的路径path = System.IO.Path.Combine(path, assemblyName + "Log");//TempLog.logging(path);//创建日志文件夹Directory.CreateDirectory(path);string dn = DateTime.Now.ToString("yyyy-MM-dd");this.curfilepath = Path.Combine(this.LogPath, assemblyName + dn + ".log");this.errorLgFile = Path.Combine(this.LogPath, assemblyName + dn + "err.log");}public void MakeLogFileName(){// 获取当前应用程序域的名称(通常是程序集名称)string assemblyName = AppDomain.CurrentDomain.FriendlyName;// 去掉路径和扩展名,只保留文件名assemblyName = Path.GetFileNameWithoutExtension(assemblyName);string dn = DateTime.Now.ToString("yyyy-MM-dd");this.curfilepath = Path.Combine(this.LogPath, assemblyName + dn + ".log");this.errorLgFile = Path.Combine(this.LogPath, assemblyName + dn + "err.log");}public void WriteLogFile(){using (StreamWriter writer = new StreamWriter(this.curfilepath, true)) // true表示追加模式  {foreach (var cnt in this.buffer){writer.WriteLine(cnt.ToString());}}}public void WriteErrorLog(){using (StreamWriter writer = new StreamWriter(this.errorLgFile, true)) // true表示追加模式  {foreach (var cnt in this.buffer){if (cnt.Level >= LogLevel.Warning)writer.WriteLine(LogContentX.TraceDetail(cnt));}}}//发现它仍然阻塞主线程//注意只有一个线程写,不能多个线程同时写文件。//请注意,Buffer.Remove(cnt) 在循环中可能会导致问题,因为从集合中移除元素会改变集合的大小,从而可能导致迭代器失效。为了避免这个问题,可以先收集需要删除的元素,然后在循环结束后统一删除它们。public void WriteLogByThread(LogBuffer logs){this.watcher.Start();this.IsWriting = true;//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None),fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1), writer2 = new StreamWriter(fs2)){foreach (var cnt in logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)writer2.WriteLine(LogContentX.TraceDetail(cnt));}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}//如果没有errlog就不写public void WriteLogByThreadV2(LogBuffer logs){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1)){foreach (var cnt in logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)errlogs.Enqueue(cnt);}}}if (errlogs.Count > 0){using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer2 = new StreamWriter(fs2)){for (int i = 0; i < errlogs.Count; i++){writer2.WriteLine(errlogs.Dequeue().ToString());}}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}public void WriteLogByThreadV3(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1)){//foreach (var cnt in queue)//{//    writer.WriteLine(cnt.ToString());//    ;//    if (cnt.Level >= LogLevel.Warning)//        errlogs.Enqueue(cnt);//}while (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}if (errlogs.Count > 0){using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer2 = new StreamWriter(fs2)){for (int i = 0; i < errlogs.Count; i++){writer2.WriteLine(errlogs.Dequeue().ToString());}}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}public void WriteLogByThreadV4(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG//            TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1)){//foreach (var cnt in queue)//{//    writer.WriteLine(cnt.ToString());//    ;//    if (cnt.Level >= LogLevel.Warning)//        errlogs.Enqueue(cnt);//}while (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}if (errlogs.Count > 0){using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer2 = new StreamWriter(fs2)){for (int i = 0; i < errlogs.Count; i++){writer2.WriteLine(LogContentX.TraceDetail(errlogs.Dequeue()));}}}}//Buffer没有上锁是希望它尽快完成操作,但有风险});this.watcher.Stop();this.IsWriting = false;if (this.lastms > 0 && this.lastms > this.maxms){this.maxms = this.lastms;}if (this.lastms > 0 && this.minms == 0)this.minms = this.lastms;if (this.lastms > 0 && this.lastms < this.minms){this.minms = this.lastms;}this.lastms = watcher.ElapsedMilliseconds;}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/69284.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka 可靠性探究—副本刨析

Kafka 的多副本机制提升了数据容灾能力。 副本通常分为数据副本与服务副本。数据副本是指在不同的节点上持久化同一份数据&#xff1b;服务副本指多个节点提供同样的服务&#xff0c;每个节点都有能力接收来自外部的请求并进行相应的处理。 1 副本刨析 1.1 相关概念 AR&…

Unity Dots学习

ISystem和SystemBase的区别 Archetype和Chunk 相同组件的实体放在一起&#xff0c;也就是我们所说的内存块&#xff08;Chunk&#xff09; Chunk有一个大小 https://blog.csdn.net/weixin_40124181/article/details/103716338 如果批量操作的entity都是同一个chunk下的效率会更…

Oracle(windows安装遇到的ORA-12545、ORA-12154、ORA-12541、ORA-12514等问题)

其实出现该问题就是监听或者服务没有配好。 G:\xiaowangzhenshuai\software\Oracle\product\11.2.0\dbhome_1\NETWORK\ADMINlistener.ora SID_LIST_LISTENER (SID_LIST (SID_DESC (SID_NAME CLRExtProc)(ORACLE_HOME G:\xiaowangzhenshuai\software\Oracle\product\11.2.0\d…

Mac上搭建k8s环境——Minikube

1、在mac上安装Minikube可执行程序 brew cask install minikub 安装后使用minikube version命令查看版本 2、安装docker环境 brew install --cask --appdir/Applications docker #安装docker open -a Docker #启动docker 3、安装kubectl curl -LO https://storage.g…

PostgreSQL 中进行数据导入和导出

在数据库管理中&#xff0c;数据的导入和导出是非常常见的操作。特别是在 PostgreSQL 中&#xff0c;提供了多种工具和方法来实现数据的有效管理。无论是备份数据&#xff0c;还是将数据迁移到其他数据库&#xff0c;或是进行数据分析&#xff0c;掌握数据导入和导出的技巧都是…

【Gitlab】虚拟机硬盘文件丢失,通过xx-flat.vmdk恢复方法

前言 由于近期过年回家&#xff0c;为了用电安全直接手动关闭了所有的电源&#xff0c;导致年后回来商上电开机后exsi上的虚拟机出现了问题。显示我的gitlab虚拟机异常。 恢复 开机之后虚拟机异常&#xff0c;通过磁盘浏览发现gitlab服务器下面的虚拟机磁盘文件只有一个xxx-f…

python的ruff简单使用

Ruff 是一个用 Rust 编写的高性能 Python 静态分析工具和代码格式化工具。它旨在提供快速的代码检查和格式化功能&#xff0c;同时支持丰富的配置选项和与现有工具的兼容性。ruff是用rust实现的python Linter&Formatter。 安装&#xff1a; conda install -c conda-forge…

第16章 Single Thread Execution设计模式(Java高并发编程详解:多线程与系统设计)

简单来说&#xff0c; Single Thread Execution就是采用排他式的操作保证在同一时刻只能有一个线程访问共享资源。 1.机场过安检 1.1非线程安全 先模拟一个非线程安全的安检口类&#xff0c;旅客(线程)分别手持登机牌和身份证接受工作人员的检查&#xff0c;示例代码如所示。…

项目练习:重写若依后端报错cannot be cast to com.xxx.model.LoginUser

文章目录 一、情景说明二、解决办法 一、情景说明 在重写若依后端服务的过程中 使用了Redis存放LoginUser对象数据 那么&#xff0c;有存就有取 在取值的时候&#xff0c;报错 二、解决办法 方法1、在TokenService中修改如下 getLoginUser 方法中&#xff1a;LoginUser u…

简述mysql 主从复制原理及其工作过程,配置一主两从并验证。

MySQL 主从复制工作过程 1、二进制日志记录&#xff08;Binary Logging&#xff09;&#xff1a; 主服务器开启二进制日志记录功能&#xff0c;将所有更改数据的操作&#xff08;如 INSERT、UPDATE、DELETE&#xff09;记录到二进制日志文件中。 2、日志传输&#xff08;Log…

Python Pandas(3):DataFrame

1 介绍 DataFrame 是 Pandas 中的另一个核心数据结构&#xff0c;类似于一个二维的表格或数据库中的数据表。它含有一组有序的列&#xff0c;每列可以是不同的值类型&#xff08;数值、字符串、布尔型值&#xff09;。DataFrame 既有行索引也有列索引&#xff0c;它可以被看做由…

Windows Docker笔记-安装docker

安装环境 操作系统&#xff1a;Windows 11 家庭中文版 docker版本&#xff1a;Docker Desktop version: 4.36.0 (175267) 注意&#xff1a; Docker Desktop 支持以下Windows操作系统&#xff1a; 支持的版本&#xff1a;Windows 10&#xff08;家庭版、专业版、企业版、教育…

Android学习20 -- 手搓App2(Gradle)

1 前言 昨天写了一个完全手搓的&#xff1a;Android学习19 -- 手搓App-CSDN博客 后面谷歌说不要用aapt&#xff0c;d8这些来搞。其实不想弄Gradle的&#xff0c;不过想着既然开始了&#xff0c;就多看一些。之前写过一篇Gradle&#xff0c;不过是最简单的编译&#xff0c;不涉…

团建 蓝桥杯省a 15

问题描述 小蓝正在和朋友们团建&#xff0c;有一个游戏项目需要两人合作&#xff0c;两个人分别拿到一棵大小为 nn 和 mm 的树&#xff0c;树上的每个结点上有一个正整数权值。 两个人需要从各自树的根结点 1 出发走向某个叶结点&#xff0c;从根到这个叶结点的路径上经过的所…

vscode 如何通过Continue引入AI 助手deepseek

第一步&#xff1a; 在deepseek 官网上注册账号&#xff0c;得到APIKeys(deepseek官网地址) 创建属于自己的APIKey,然后复制这个key,(注意保存自己的key)! 第二步&#xff1a; 打开vscode,在插件市场安装Continue插件, 点击设置&#xff0c;添加deepseek模型&#xff0c;默认…

计算机网络——三种交换技术

目录 电路交换——用于电话网络 电路交换的优点&#xff1a; 电路交换的缺点&#xff1a; 报文交换——用于电报网络 报文交换的优点&#xff1a; 报文交换的缺点&#xff1a; 分组交换——用于现代计算机网络 分组交换的优点&#xff1a; 分组交换的缺点 电路交换——…

PostgreSQL函数自动Commit/Rollback所带来的问题

一、综述 今天在PostgreSQL遇到一个奇怪的现象&#xff0c;简而言之&#xff0c;是想用函数&#xff08;存储过程&#xff09;实现插入记录&#xff0c;整个过程没报错但事后却没找到记录&#xff01;忙活半天&#xff0c;才发现原因是PostgreSQL函数&#xff08;存储过程&…

linux 进程补充

环境变量 基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪 里&#xff0c;但是照样可以链接成功&#…

Spring Boot常用注解深度解析:从入门到精通

今天&#xff0c;这篇文章带你将深入理解Spring Boot中30常用注解&#xff0c;通过代码示例和关系图&#xff0c;帮助你彻底掌握Spring核心注解的使用场景和内在联系。 一、启动类与核心注解 1.1 SpringBootApplication 组合注解&#xff1a; SpringBootApplication Confi…

前部分知识复习05

一、多级渐远贴图MipMap 选择贴图&#xff0c;可以勾选贴图的多级渐远效果 [IntRange]_MipMap("MipMap",Range(0,12))0 //多级渐远贴图的LOD调节滑杆 _MipMapTexture("MipMapTexture",2D)"white"{} //定义多级渐远贴图 多级渐远贴图的采样…