add test solution and try to fix get id code bug

This commit is contained in:
SikongJueluo 2025-04-15 20:09:34 +08:00
parent 5e2da17c28
commit e8ec4c2a86
No known key found for this signature in database
10 changed files with 127 additions and 79 deletions

View File

@ -10,3 +10,7 @@ publish: _show-dir
[working-directory: "server"] [working-directory: "server"]
run-server: _show-dir run-server: _show-dir
dotnet run dotnet run
[working-directory: "server.test"]
test-server: _show-dir
dotnet test

2
server.test/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
bin
obj

View File

@ -0,0 +1,36 @@
namespace server.test.UDPServer;
public class UnitTest1
{
[Fact]
public void UDPDataDeepClone()
{
var udpData = new UDPData()
{
DateTime = DateTime.Now,
Address = "127.0.0.1",
Port = 1234,
Data = new byte[] { 0xf0, 00, 00, 00 },
HasRead = false
};
var cloneUdpData = udpData.DeepClone();
Assert.Equal(udpData.DateTime, cloneUdpData.DateTime);
Assert.Equal(udpData.Address, cloneUdpData.Address);
Assert.Equal(udpData.Port, cloneUdpData.Port);
Assert.Equal(udpData.Data, cloneUdpData.Data);
Assert.Equal(udpData.HasRead, cloneUdpData.HasRead);
udpData.DateTime = DateTime.Now;
udpData.Address = "192.168.1.1";
udpData.Port = 33000;
udpData.Data = new byte[] { 0x0f, 00, 00, 00 };
udpData.HasRead = true;
Assert.NotEqual(udpData.DateTime, cloneUdpData.DateTime);
Assert.NotEqual(udpData.Address, cloneUdpData.Address);
Assert.NotEqual(udpData.Port, cloneUdpData.Port);
Assert.NotEqual(udpData.Data, cloneUdpData.Data);
Assert.NotEqual(udpData.HasRead, cloneUdpData.HasRead);
}
}

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\server\server.csproj" />
</ItemGroup>
</Project>

View File

@ -79,8 +79,6 @@ try
// Setup Program // Setup Program
MsgBus.Init(); MsgBus.Init();
// if (app.Environment.IsDevelopment()) MsgBus.UDPServer.EnableDebugMode = true;
MsgBus.UDPServer.EnableDebugMode = true;
// Router // Router
// API Get // API Get

View File

@ -60,6 +60,11 @@
"finalMinLevel": "Info", "finalMinLevel": "Info",
"writeTo": "Console" "writeTo": "Console"
}, },
{
"logger": "server",
"finalMinLevel": "Trace",
"writeTo": "EachFile"
},
{ {
"logger": "server.*", "logger": "server.*",
"finalMinLevel": "Trace", "finalMinLevel": "Trace",

View File

@ -50,14 +50,14 @@ namespace Common
{ {
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
num += Convert.ToUInt64(bytes[len - 1 - i] << (i << 3)); num += Convert.ToUInt64((UInt64)bytes[len - 1 - i] << (i << 3));
} }
} }
else else
{ {
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
num += Convert.ToUInt64(bytes[i] << ((int)(len - 1 - i) << 3)); num += Convert.ToUInt64((UInt64)bytes[i] << ((int)(len - 1 - i) << 3));
} }
} }

View File

@ -245,7 +245,7 @@ class Jtag
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send Address Package Failed!"); if (!ret) throw new Exception("Send Address Package Failed!");
// Wait for Ack // Wait for Read Ack
if (!MsgBus.IsRunning) if (!MsgBus.IsRunning)
throw new Exception("Message Bus not Working!"); throw new Exception("Message Bus not Working!");
@ -261,7 +261,7 @@ class Jtag
if (retPackLen != 4) if (retPackLen != 4)
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"); throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
return (uint)(NumberProcessor.BytesToNumber(retPackOpts.Data)); return Convert.ToUInt32(NumberProcessor.BytesToNumber(retPackOpts.Data).Value);
} }
public async ValueTask<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command) public async ValueTask<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command)
@ -279,6 +279,11 @@ class Jtag
opts.IsWrite = true; opts.IsWrite = true;
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send 1st address package failed!"); if (!ret) throw new Exception("Send 1st address package failed!");
// Send Data Package
ret = await UDPClientPool.SendDataPackAsync(ep,
new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
if (!ret) throw new Exception("Send data package failed!");
// Check Msg Bus // Check Msg Bus
if (!MsgBus.IsRunning) if (!MsgBus.IsRunning)
throw new Exception("Message bus not working!"); throw new Exception("Message bus not working!");
@ -288,10 +293,6 @@ class Jtag
if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful) if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful)
throw new Exception("Send address package failed"); throw new Exception("Send address package failed");
} }
// Send Data Package
ret = await UDPClientPool.SendDataPackAsync(ep,
new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
if (!ret) throw new Exception("Send data package failed!");
// Read Jtag State Register // Read Jtag State Register
opts.IsWrite = false; opts.IsWrite = false;

View File

@ -1,7 +1,7 @@
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks;
using DotNext; using DotNext;
using DotNext.Threading; using DotNext.Threading;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -30,6 +30,24 @@ public class UDPData
/// </summary> /// </summary>
public required bool HasRead { get; set; } public required bool HasRead { get; set; }
/// <summary>
/// 深度拷贝对象
/// </summary>
/// <returns>UDPData</returns>
public UDPData DeepClone()
{
var cloneData = new byte[this.Data.Length];
Buffer.BlockCopy(this.Data, 0, cloneData, 0, this.Data.Length);
return new UDPData()
{
DateTime = this.DateTime,
Address = new string(this.Address),
Port = this.Port,
Data = cloneData,
HasRead = this.HasRead
};
}
/// <summary> /// <summary>
/// 将UDP Data 转化为Json 格式字符串 /// 将UDP Data 转化为Json 格式字符串
/// </summary> /// </summary>
@ -56,11 +74,6 @@ public class UDPServer
private Dictionary<string, List<UDPData>> udpData = new Dictionary<string, List<UDPData>>(); private Dictionary<string, List<UDPData>> udpData = new Dictionary<string, List<UDPData>>();
private AsyncReaderWriterLock udpDataLock = new AsyncReaderWriterLock(1); private AsyncReaderWriterLock udpDataLock = new AsyncReaderWriterLock(1);
/// <summary>
/// 是否开启Debug模式
/// </summary>
public bool EnableDebugMode { get; set; }
/// <summary> /// <summary>
/// Construct a udp server with fixed port /// Construct a udp server with fixed port
/// </summary> /// </summary>
@ -90,11 +103,18 @@ public class UDPServer
/// </summary> /// </summary>
/// <param name="ipAddr"> IP Address</param> /// <param name="ipAddr"> IP Address</param>
/// <param name="timeout"> Read and Write Wait for Milliseconds </param> /// <param name="timeout"> Read and Write Wait for Milliseconds </param>
/// <param name="callerName">调用函数名称</param>
/// <param name="callerLineNum">调用函数位置</param>
/// <returns>UDP Data</returns> /// <returns>UDP Data</returns>
public Optional<UDPData> FindData(string ipAddr, int timeout = 1000) public Optional<UDPData> FindData(
string ipAddr, int timeout = 1000,
[CallerMemberName] string callerName = "",
[CallerLineNumber] int callerLineNum = 0)
{ {
UDPData? data = null; UDPData? data = null;
logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr} UDP Data");
var startTime = DateTime.Now; var startTime = DateTime.Now;
var isTimeout = false; var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout); var timeleft = TimeSpan.FromMilliseconds(timeout);
@ -105,7 +125,7 @@ public class UDPServer
{ {
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0) if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
{ {
data = udpData[ipAddr][0]; data = udpData[ipAddr][0].DeepClone();
udpData[ipAddr].RemoveAt(0); udpData[ipAddr].RemoveAt(0);
logger.Debug($"Find UDP Data: {data.ToString()}"); logger.Debug($"Find UDP Data: {data.ToString()}");
break; break;
@ -132,15 +152,22 @@ public class UDPServer
/// </summary> /// </summary>
/// <param name="ipAddr"> 目标IP地址 </param> /// <param name="ipAddr"> 目标IP地址 </param>
/// <param name="timeout">超时时间</param> /// <param name="timeout">超时时间</param>
/// <param name="callerName">调用函数名称</param>
/// <param name="callerLineNum">调用函数位置</param>
/// <returns> /// <returns>
/// 异步Optional 数据包: /// 异步Optional 数据包:
/// Optional 为空时,表明找不到数据; /// Optional 为空时,表明找不到数据;
/// Optional 存在时,为最先收到的数据 /// Optional 存在时,为最先收到的数据
/// </returns> /// </returns>
public async ValueTask<Optional<UDPData>> FindDataAsync(string ipAddr, int timeout = 1000) public async ValueTask<Optional<UDPData>> FindDataAsync(
string ipAddr, int timeout = 1000,
[CallerMemberName] string callerName = "",
[CallerLineNumber] int callerLineNum = 0)
{ {
UDPData? data = null; UDPData? data = null;
logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr} UDP Data");
var startTime = DateTime.Now; var startTime = DateTime.Now;
var isTimeout = false; var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout); var timeleft = TimeSpan.FromMilliseconds(timeout);
@ -151,7 +178,7 @@ public class UDPServer
{ {
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0) if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
{ {
data = udpData[ipAddr][0]; data = udpData[ipAddr][0].DeepClone();
udpData[ipAddr].RemoveAt(0); udpData[ipAddr].RemoveAt(0);
logger.Debug($"Find UDP Data: {data.ToString()}"); logger.Debug($"Find UDP Data: {data.ToString()}");
break; break;
@ -215,7 +242,7 @@ public class UDPServer
} }
/// <summary> /// <summary>
/// 异步等待读响应或写响应 /// 异步等待写响应
/// </summary> /// </summary>
/// <param name="address">IP地址</param> /// <param name="address">IP地址</param>
/// <param name="port">UDP 端口</param> /// <param name="port">UDP 端口</param>
@ -266,6 +293,7 @@ public class UDPServer
private void ReceiveHandler(IAsyncResult res) private void ReceiveHandler(IAsyncResult res)
{ {
logger.Trace("Enter handler");
var remoteEP = new IPEndPoint(IPAddress.Any, listenPort); var remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
byte[] bytes = listener.EndReceive(res, ref remoteEP); byte[] bytes = listener.EndReceive(res, ref remoteEP);
@ -278,67 +306,13 @@ public class UDPServer
} }
// If enable Debug mode, exec Debug handler
if (EnableDebugMode)
{
DebugHandler(new IPEndPoint(IPAddress.Parse("127.0.0.1"), this.listenPort), bytes);
}
else
{
// Handle Package // Handle Package
PrintData(RecordUDPData(bytes, remoteEP)); PrintData(RecordUDPData(bytes, remoteEP));
}
BEGIN_RECEIVE: BEGIN_RECEIVE:
listener.BeginReceive(new AsyncCallback(ReceiveHandler), null); listener.BeginReceive(new AsyncCallback(ReceiveHandler), null);
} }
private void DebugHandler(IPEndPoint ep, byte[] bytes)
{
// Print Receive Data
var data = new UDPData()
{
Address = ep.Address.ToString(),
Port = ep.Port,
Data = bytes,
DateTime = DateTime.Now,
HasRead = false,
};
PrintData(data);
// Handle Pack Type
var sign = bytes[0];
if (sign == (byte)WebProtocol.PackSign.SendAddr)
{
var resData = WebProtocol.SendAddrPackage.FromBytes(bytes);
if (!resData.IsSuccessful)
{
logger.Warn("DebugHandler: Convert to SendAddrPackage failed");
return;
}
if (resData.Value.Options.IsWrite)
{
var pack = new WebProtocol.RecvRespPackage(resData.Value.Options.CommandID, true);
SendBytes(ep, pack.ToBytes());
}
else
{
var pack = new WebProtocol.RecvDataPackage(resData.Value.Options.CommandID, true, [0, 0, 0, 0]);
SendBytes(ep, pack.ToBytes());
}
}
else if (sign == (byte)WebProtocol.PackSign.SendData)
{
}
else
{
SendString(ep, "DebugHandler: Receive Data");
}
logger.Trace("DebugHandler: send pack successfully");
}
private bool SendBytes(IPEndPoint endPoint, byte[] buf) private bool SendBytes(IPEndPoint endPoint, byte[] buf)
{ {
var sendLen = listener.Send(buf, endPoint); var sendLen = listener.Send(buf, endPoint);
@ -380,7 +354,9 @@ public class UDPServer
} }
else else
{ {
udpData.Add(remoteAddress, new List<UDPData>([data])); var list = new List<UDPData>();
list.Add(data);
udpData.Add(remoteAddress, list);
logger.Trace("Receive data from new client"); logger.Trace("Receive data from new client");
} }

View File

@ -478,7 +478,7 @@ namespace WebProtocol
{ {
if (bytes[0] != (byte)PackSign.RecvResp) if (bytes[0] != (byte)PackSign.RecvResp)
throw new ArgumentException( throw new ArgumentException(
"The sign of bytes is not RecvData Package!", "The sign of bytes is not RecvResp Package!",
nameof(bytes) nameof(bytes)
); );
return new RecvRespPackage(bytes[1], bytes[2]); return new RecvRespPackage(bytes[1], bytes[2]);