server finish nlog

This commit is contained in:
SikongJueluo 2025-04-10 21:53:21 +08:00
parent 143d6c634b
commit c9660633f0
No known key found for this signature in database
8 changed files with 247 additions and 45 deletions

View File

@ -1,5 +1,6 @@
using System.Reflection;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using NLog;
using NLog.Web;
@ -9,6 +10,7 @@ var logger = NLog.LogManager.Setup()
.GetCurrentClassLogger();
logger.Debug("Init Main...");
try
{
var builder = WebApplication.CreateBuilder(args);
@ -21,6 +23,14 @@ try
builder.Host.UseNLog();
builder.Services.AddEndpointsApiExplorer();
// Add Json.Net Serializer
builder.Services.AddControllersWithViews().AddNewtonsoftJson(options =>
{
// Configure Newtonsoft.Json options here
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
// Add Swagger
builder.Services.AddSwaggerGen(options =>
{
@ -70,10 +80,14 @@ try
MsgBus.Init();
// Router
// API Get
app.MapGet("/", () => Results.Redirect("/swagger"));
app.MapGet("/api/GetRecvDataArray", Router.API.GetRecvDataArray);
app.MapPut("/api/SendString", Router.API.SendString);
// API Put
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
// API Jtag Put
app.MapPut("/api/jtag/RunCommand", Router.API.Jtag.RunCommand);
app.MapPut("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode);
@ -89,9 +103,11 @@ finally
{
// Close UDP Server
logger.Info("Program is Closing now...");
MsgBus.Exit();
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
// Close Program
MsgBus.Exit();
}

View File

@ -28,6 +28,10 @@
"type": "File",
"fileName": "./log/web-all-${shortdate}.log"
},
"EachFile": {
"type": "File",
"fileName": "./log/${logger}-${shortdate}.log"
},
"Console": {
"type": "ColoredConsole"
}
@ -55,6 +59,16 @@
"logger": "Microsoft.Hosting.Lifetime*",
"finalMinLevel": "Info",
"writeTo": "Console"
},
{
"logger": "server.*",
"finalMinLevel": "Trace",
"writeTo": "EachFile"
},
{
"logger": "server.*",
"finalMinLevel": "Debug",
"writeTo": "Console"
}
]
}

View File

@ -13,6 +13,7 @@
<ItemGroup>
<PackageReference Include="DotNext" Version="5.19.1" />
<PackageReference Include="DotNext.Threading" Version="5.19.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.4" />
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" />

View File

@ -254,10 +254,10 @@ class Jtag
throw new Exception("Get None after Time out!");
var recvData = data.Value;
if (recvData.addr != address || recvData.port != port)
if (recvData.Address != address || recvData.Port != port)
throw new Exception("Receive Data From Wrong Board!");
var retPack = RecvDataPackage.FromBytes(recvData.data);
var retPack = RecvDataPackage.FromBytes(recvData.Data);
if (!retPack.IsSuccessful)
throw new Exception("Not RecvDataPackage!", retPack.Error);
@ -304,10 +304,10 @@ class Jtag
throw new Exception("Get None after Time out!");
var recvData = data.Value;
if (recvData.addr != address || recvData.port != port)
if (recvData.Address != address || recvData.Port != port)
throw new Exception("Receive Data From Wrong Board!");
var retPack = RecvDataPackage.FromBytes(recvData.data);
var retPack = RecvDataPackage.FromBytes(recvData.Data);
if (!retPack.IsSuccessful)
throw new Exception("Not RecvDataPackage!", retPack.Error);

View File

@ -1,5 +1,3 @@
/// <summary>
/// 多线程通信总线
/// </summary>

View File

@ -1,13 +1,33 @@
using System.Net;
using Common;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace Router
{
struct Response
/// <summary>
/// Custom Web Http Response
/// </summary>
public class Response
{
public bool IsSuccess;
public object? Data;
/// <summary>
/// 是否成功执行
/// </summary>
public bool IsSuccess { get; set; }
/// <summary>
/// 数据
/// </summary>
public object? Data { get; set; }
/// <summary>
/// 转换为Json格式的字符串
/// </summary>
/// <returns>Json字符串</returns>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
/// <summary>
@ -15,6 +35,9 @@ namespace Router
/// </summary>
class API
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private const string LOCALHOST = "127.0.0.1";
/// <summary>
/// 发送字符串
/// </summary>
@ -64,8 +87,36 @@ namespace Router
else { return Results.Json(new Response() { IsSuccess = false }); }
}
[HttpGet()]
public static async ValueTask<IResult> GetRecvDataArray(string address)
{
var ret = await MsgBus.UDPServer.GetDataArrayAsync(address);
if (ret.HasValue)
{
var dataJson = JsonConvert.SerializeObject(ret.Value);
logger.Debug($"Get Receive Successfully: {dataJson}");
return TypedResults.Ok(new Response
{
IsSuccess = true,
Data = ret.Value,
});
}
else
{
logger.Debug("Get Receive Failed");
return TypedResults.Json(new Response
{
IsSuccess = false,
Data = ""
});
}
}
public class Jtag
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
/// <summary>
/// 执行一个Jtag命令
/// </summary>

View File

@ -3,26 +3,36 @@ using System.Net.Sockets;
using System.Text;
using DotNext;
using DotNext.Threading;
using Newtonsoft.Json;
/// <summary> UDP接受数据包格式 </summary>
public struct UDPData
public class UDPData
{
/// <summary>
/// 接受到的时间
/// </summary>
public DateTime datetime;
public DateTime DateTime { get; set; }
/// <summary>
/// 发送来源的IP地址
/// </summary>
public string addr;
public string Address { get; set; }
/// <summary>
/// 发送来源的端口号
/// </summary>
public int port;
public int Port { get; set; }
/// <summary>
/// 接受到的数据
/// </summary>
public byte[] data;
public byte[] Data { get; set; }
/// <summary>
/// 将UDP Data 转化为Json 格式字符串
/// </summary>
/// <returns>json字符串</returns>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
/// <summary>
@ -30,6 +40,8 @@ public struct UDPData
/// </summary>
public class UDPServer
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private int listenPort;
private UdpClient listener;
private IPEndPoint groupEP;
@ -142,6 +154,38 @@ public class UDPServer
}
}
public async ValueTask<Optional<List<UDPData>>> GetDataArrayAsync(string ipAddr, int timeout = 1000)
{
List<UDPData>? data = null;
var startTime = DateTime.Now;
var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout);
while (!isTimeout)
{
using (await udpDataLock.AcquireReadLockAsync(timeleft))
{
if (udpData.ContainsKey(ipAddr))
{
data = udpData[ipAddr];
}
}
timeleft = DateTime.Now.Subtract(startTime);
isTimeout = timeleft >= TimeSpan.FromMilliseconds(timeout);
}
if (data == null)
{
return Optional.None<List<UDPData>>();
}
else
{
return Optional.Some((List<UDPData>)data);
}
}
private void ReceiveHandler(IAsyncResult res)
{
var remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
@ -150,6 +194,8 @@ public class UDPServer
// Handle RemoteEP
string remoteStr = "Unknown";
using (udpDataLock.AcquireWriteLock())
{
if (remoteEP is not null)
{
var remoteAddress = remoteEP.Address.ToString();
@ -160,24 +206,31 @@ public class UDPServer
var listData = udpData[remoteAddress];
listData.Add(new UDPData()
{
addr = remoteAddress,
port = remotePort,
data = bytes,
datetime = nowtime,
Address = remoteAddress,
Port = remotePort,
Data = bytes,
DateTime = nowtime,
});
logger.Trace("Receive data from old client");
}
else
{
udpData.Add(remoteAddress, new List<UDPData>([new UDPData(){
addr = remoteAddress,
port = remotePort,
data = bytes,
datetime = nowtime,
Address = remoteAddress,
Port = remotePort,
Data = bytes,
DateTime = nowtime,
}]));
logger.Trace("Receive data from new client");
}
remoteStr = $"{remoteAddress}:{remotePort}";
}
else
{
logger.Warn("Receive data from unknown client");
}
}
// Handle Package
var sign = bytes[0];
@ -212,14 +265,35 @@ public class UDPServer
recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
}
Console.WriteLine($"Receive Data from {remoteStr} at {nowtime.ToString()}:");
Console.WriteLine($"Original Data: {BitConverter.ToString(bytes).Replace("-", " ")}");
if (recvData.Length != 0) Console.WriteLine(recvData);
Console.WriteLine();
logger.Debug($"Receive Data from {remoteStr} at {nowtime.ToString()}:");
logger.Debug($"Original Data: {BitConverter.ToString(bytes).Replace("-", " ")}");
if (recvData.Length != 0) logger.Debug(recvData);
RecordAllData();
listener.BeginReceive(new AsyncCallback(ReceiveHandler), null);
}
/// <summary>
/// 将所有数据输出到log中
/// </summary>
/// <returns> void </returns>
public void RecordAllData()
{
using (udpDataLock.AcquireReadLock())
{
logger.Debug("Ready Data:");
foreach (var ip in udpData)
{
foreach (var data in ip.Value)
{
logger.Debug(data.ToString());
}
}
}
}
/// <summary>
/// Start UDP Server
/// </summary>

View File

@ -141,6 +141,12 @@ namespace WebProtocol
this.address = address;
}
/// <summary>
/// 使用二进制参数构建地址包
/// </summary>
/// <param name="commandType">二进制命令类型</param>
/// <param name="burstLength">突发长度</param>
/// <param name="address">写入或读取的地址</param>
public SendAddrPackage(byte commandType, byte burstLength, UInt32 address)
{
this.commandType = commandType;
@ -182,6 +188,12 @@ namespace WebProtocol
return JsonConvert.SerializeObject(opts);
}
/// <summary>
/// 根据字节数组构建地址包
/// </summary>
/// <param name="bytes">字节数组</param>
/// <param name="checkSign">是否校验地址包包头</param>
/// <returns>地址包</returns>
public static Result<SendAddrPackage> FromBytes(byte[] bytes, bool checkSign = true)
{
if (bytes.Length != 8)
@ -205,17 +217,28 @@ namespace WebProtocol
}
}
/// <summary> 数据包 </summary>
public struct SendDataPackage
{
readonly byte sign = (byte)PackSign.SendData;
readonly byte[] _reserved = new byte[3];
readonly byte[] bodyData;
/// <summary>
/// 根据数据内容构建数据包
/// </summary>
/// <param name="bodyData">数据</param>
public SendDataPackage(byte[] bodyData)
{
this.bodyData = bodyData;
_ = _reserved;
}
/// <summary>
/// 将数据包转化为字节数组
/// </summary>
/// <returns>字节数组</returns>
public byte[] ToBytes()
{
var bodyDataLen = bodyData.Length;
@ -231,7 +254,7 @@ namespace WebProtocol
}
/// <summary> FPGA->Server 读数据包 </summary>
/// <summary> FPGA->Server 读响应包 </summary>
public struct RecvDataPackage
{
readonly byte sign = (byte)PackSign.RecvData;
@ -241,21 +264,24 @@ namespace WebProtocol
readonly byte[] bodyData;
/// <summary>
/// FPGA->Server 读数据
/// FPGA->Server 读响应
/// 构造函数
/// </summary>
/// <param name="commandID"> 任务ID号 </param>
/// <param name="resp"> 读数据包响应 </param>
/// <param name="resp"> 读响应包响应 </param>
/// <param name="bodyData"> 数据 </param>
public RecvDataPackage(byte commandID, byte resp, byte[] bodyData)
{
this.commandID = commandID;
this.resp = resp;
this.bodyData = bodyData;
_ = this.sign;
_ = this._reserved;
}
/// <summary>
/// 获取读数据包选项
/// 获取读响应包选项
/// </summary>
public RecvPackOptions Options
{
@ -271,6 +297,11 @@ namespace WebProtocol
}
}
/// <summary>
/// 从字节数组构建读响应包
/// </summary>
/// <param name="bytes">字节数组</param>
/// <returns>读响应包</returns>
public static Result<RecvDataPackage> FromBytes(byte[] bytes)
{
if (bytes[0] != (byte)PackSign.RecvData)
@ -282,6 +313,7 @@ namespace WebProtocol
}
}
/// <summary> 写响应包 </summary>
public struct RecvRespPackage
{
readonly byte sign = (byte)PackSign.RecvResp;
@ -289,12 +321,23 @@ namespace WebProtocol
readonly byte resp;
readonly byte _reserved = 0;
/// <summary>
/// 构建写响应包
/// </summary>
/// <param name="commandID">任务ID</param>
/// <param name="resp">写响应</param>
public RecvRespPackage(byte commandID, byte resp)
{
this.commandID = commandID;
this.resp = resp;
_ = this.sign;
_ = this._reserved;
}
/// <summary>
/// 获取写响应包选项
/// </summary>
public RecvPackOptions Options
{
get
@ -309,6 +352,11 @@ namespace WebProtocol
}
}
/// <summary>
/// 从字节数组构建写响应包
/// </summary>
/// <param name="bytes">字节数组</param>
/// <returns>写响应包</returns>
public static Result<RecvRespPackage> FromBytes(byte[] bytes)
{
if (bytes[0] != (byte)PackSign.RecvResp)