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;}}
}
相关文章:
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 …...
PromptSource安装报错
一、现象 运行命令:streamlit run promptsource/app.py 报错: streamlit run promptsource/app.py Traceback (most recent call last): File "/usr/local/bin/streamlit", line 5, in <module> from streamlit.cli import main File …...
前端学习-页面尺寸事件以及阻止默认行为(三十三)
目录 前言 页面尺寸事件 语法 检测屏幕宽度 获取宽高 元素尺寸的位置 总结 示例代码 阻止默认行为 阻止冒泡 语法 阻止冒泡如何做 阻止元素默认行为如何做 总结 前言 晚上好各位 页面尺寸事件 会在窗口尺寸改变的时候触发条件 语法 window.addEventListener(…...
Kafka 入门与实战
一、Kafka 基础 1.1 创建topic kafka-topics.bat --bootstrap-server localhost:9092 --topic test --create 1.2 查看消费者偏移量位置 kafka-consumer-groups.bat --bootstrap-server localhost:9092 --describe --group test 1.3 消息的生产与发送 #生产者 kafka-cons…...
5 计算机网络
5 计算机网络 5.1 OSI/RM七层模型 5.2 TCP/IP协议簇 5.2.1:常见协议基础 一、 TCP是可靠的,效率低的; 1.HTTP协议端口默认80,HTTPSSL之后成为HTTPS协议默认端口443。 2.对于0~1023一般是默认的公共端口不需要注册,1024以后的则需…...
【华为OD机考】华为OD笔试真题解析(1)--AI处理器组合
一、题目描述 某公司研发了一款高性能AI处理器,每台物理设备具备8颗AI处理器,编号分别为0、1、2、3、4、5、6、7。 编号0~3的处理器处于同一链路中,编号4~7的处理器处于另外一个链路中,不同链路中的处理器不能通信,如…...
程序员也可以这样赚钱
最近有朋友和我交流了关于程序员副业的想法,我想借这个机会对目前软件开发常用的兼职平台做一个梳理。 以下是程序员接副业的靠谱平台推荐,结合政策合规性、平台口碑及实际操作性整理,覆盖国内外主流选择: 一、国内综合型平台 程序…...
VMware虚拟机安装、创建Ubuntu虚拟机及汉化设置全流程详细教程
一、安装VMware Workstation 下载VMware 访问官网:https://www.vmware.com 选择适合的版本(如 Workstation Pro 或 VMware Player,后者免费)。完成下载后运行安装程序。 网盘下载: 链接: https://pan.baidu.com/s/1MQ…...
HTTP协议学习大纲
第一阶段:HTTP基础概念 互联网与Web基础 理解Web工作原理:客户端-服务器模型URL与URI的结构及区别端口、协议、域名概念 HTTP协议概览 HTTP的作用与特点(无状态、无连接、可扩展)HTTP协议版本演进(0.9 → 1.0 → 1.1 …...
系统URL整合系列视频四(需求介绍补充)
视频 系统URL整合系列视频四(需求补充说明) 视频介绍 (全国)大型分布式系统Web资源URL整合需求(补充)讲解。当今社会各行各业对软件系统的web资源访问权限控制越来越严格,控制粒度也越来越细。…...
21.2.7 综合示例
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 【例 21.7】【项目:code21-007】填充职员表并打印。 本例使用到的Excel文件为:职员信息登记表.xlsx&#x…...
【大模型】DeepSeek与chatGPT的区别以及自身的优势
目录 一、前言二、核心技术对比2.1 模型架构设计2.1.1 ChatGPT的Transformer架构2.1.2 DeepSeek的混合架构 2.2 训练数据体系2.2.1 ChatGPT的数据特征2.2.2 DeepSeek的数据策略 三、应用场景对比3.1 通用场景表现3.1.1 ChatGPT的强项领域3.2.2 DeepSeek的专项突破 3.3 响应效率…...
burpsuite抓取html登陆和上传数据包
一、burpsuite抓取html登陆数据包 1、先写一个html格式的登陆页面 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><title>这是标签</title></head> <body> <hr><!-- 登陆表单 …...
python 使用OpenAI Whisper进行显卡推理语音翻译
目录 一、Whisper简介 二、模型资料 三、实操案例 3.1 默认使用CPU进行推理 3.2 使用GPU进行推理 四、性能分析 一、Whisper简介 Whisper由 OpenAI 开发的这款强大模型,能轻松将语音转化为文字,并且支持多种语言(如英语、中文、西班牙语等),让全球沟通无障碍。 不仅…...
余数相同问题(信息学奥赛一本通-1080)
【题目描述】 已知三个正整数a,b,c。现有一个大于1的整数x,将其作为除数分别除a,b,c,得到的余数相同。请问满足上述条件的x的最小值是多少?数据保证x有解。 【输入】 一行,三个不大于…...
用 Python 给 Excel 表格截图(20250207)
我搜索了网络上的方案,感觉把 Excel 表格转换为 HTML 再用 platwright 截图是比较顺畅的路径,因为有顺畅的工具链。如果使用的是 Windows 系统则不需要阅读此文,因为 win32com 库更方便。这篇文章中 Excel 转 HTML 的方案,主要弥补…...
Linux 安装 Ollama
1、下载地址 Download Ollama on Linux 2、有网络直接执行 curl -fsSL https://ollama.com/install.sh | sh 命令 3、下载慢的解决方法 1、curl -fsSL https://ollama.com/install.sh -o ollama_install.sh 2、sed -i s|https://ollama.com/download/ollama-linux|https://…...
使用Ollama本地部署deepseek
1、下载安装Ollama 前往下载页面 https://ollama.com/download下载好安装包,如同安装软件一样,直接安装即可 win中默认为C盘,如果需要修改到其他盘,查找具体教程 运行list命令,检查是否安装成功 2、修改模型下载的…...
如何在RTACAR中配置IP多播(IP Multicast)
一、什么是IP多播 IP多播(IP Multicast)是一种允许数据包从单一源地址发送到多个目标地址的技术,是一种高效的数据传输方式。 多播地址是专门用于多播通信的IP地址,范围从 224.0.0.0到239.255.255.255 与单播IP地址不同&#x…...
2025年最新版武书连SCD期刊(中国科学引文数据库)来源期刊已更新,可下载PDF版!需要的作者进来了解~
2025年最新版武书连SCD期刊(中国科学引文数据库)来源期刊已更新! 官网是不提供免费查询的。小编给大家两个路径,无需下载PDF,随时随地都能查25版SCD目录。 路径一:中州期刊联盟官网,25版SCD目…...
已验证正常,Java输入字符串生成PDF文件
Java输入字符串生成PDF文件过程: 在Java开发中,如何将字符串转换为 PDF 是一个常见的需求。网上找了很多例子都无法生成,经过多次尝试,终于实现了,特此记录一下。 1、引入pom.xml 添加所需的依赖 <dependency>&…...
存储异常导致的Oracle重大生产故障
📢📢📢📣📣📣 作者:IT邦德 中国DBA联盟(ACDU)成员,10余年DBA工作经验 Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主,全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯…...
基于Java的远程视频会议系统(源码+系统+论文)
第一章 概述 1.1 本课题的研究背景 随着人们对视频和音频信息的需求愈来愈强烈,追求远距离的视音频的同步交互成为新的时尚。近些年来,依托计算机技术、通信技术和网络条件的发展,集音频、视频、图像、文字、数据为一体的多媒体信息ÿ…...
C++ Primer 成员访问运算符
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
使用云效解决docker官方镜像拉取不到的问题
目录 前言原文地址测试jenkins构建结果:后续使用说明 前言 最近经常出现docker镜像进行拉取不了,流水线挂掉的问题,看到一个解决方案: 《借助阿里个人版镜像仓库云效实现全免费同步docker官方镜像到国内》 原文地址 https://developer.aliyun.com/artic…...
Oracle中与 NLS(National Language Support,国家语言支持) 相关的参数
在Oracle中,NLS_DATABASE_PARAMETERS 和 NLS_INSTANCE_PARAMETERS 是两个重要的视图,用于存储与 NLS(National Language Support,国家语言支持) 相关的参数。它们的作用和区别如下: 1. NLS_DATABASE_PARAME…...
【Pytorch实战教程】Python探索利器:dir与help深度解析(PyTorch实战演示)
文章目录 Python探索利器:dir与help深度解析(PyTorch实战演示)一、前言:代码世界的探险装备二、dir():对象结构探测器1. 基础用法揭秘2. PyTorch实战应用三、help():内置文档浏览器1. 基础使用姿势2. 深度学习场景实战四、组合技:探索神经网络模块1. 模块结构探测2. 类方…...
【DeepSeek】DeepSeek小模型蒸馏与本地部署深度解析DeepSeek小模型蒸馏与本地部署深度解析
一、引言与背景 在人工智能领域,大型语言模型(LLM)如DeepSeek以其卓越的自然语言理解和生成能力,推动了众多应用场景的发展。然而,大型模型的高昂计算和存储成本,以及潜在的数据隐私风险,限制了…...
【共享文件夹】使用Samba服务可在Ubuntu和Windows系统之间共享一个实际的文件夹
目标:在Ubuntu和Windows系统之间共享一个实际的文件夹,并能够共同编辑其中的文件 安装Samba创建共享文件夹配置Samba设置Samba密码重启Samba服务以应用更改:在Windows中访问共享文件夹如果客户机无法访问 Samba 服务器,解决方法①…...
3D图形学与可视化大屏:什么是几何着色器,有什么功能和应用。
一、几何着色器的定义 在 3D 图形学和可视化大屏中,几何着色器是一种可编程的图形处理单元(GPU)着色器阶段。它位于顶点着色器和片段着色器之间,主要负责处理由顶点着色器输出的几何图形数据。 几何着色器以图元(如点…...
