diff --git a/.justfile b/.justfile
index 7df70f6..0770d72 100644
--- a/.justfile
+++ b/.justfile
@@ -10,3 +10,7 @@ publish: _show-dir
[working-directory: "server"]
run-server: _show-dir
dotnet run
+
+[working-directory: "server.test"]
+test-server: _show-dir
+ dotnet test
diff --git a/server.test/.gitignore b/server.test/.gitignore
new file mode 100644
index 0000000..1746e32
--- /dev/null
+++ b/server.test/.gitignore
@@ -0,0 +1,2 @@
+bin
+obj
diff --git a/server.test/UDPServerTest.cs b/server.test/UDPServerTest.cs
new file mode 100644
index 0000000..cc7a80e
--- /dev/null
+++ b/server.test/UDPServerTest.cs
@@ -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);
+ }
+}
diff --git a/server.test/server.test.csproj b/server.test/server.test.csproj
new file mode 100644
index 0000000..2bcffed
--- /dev/null
+++ b/server.test/server.test.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net9.0
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/Program.cs b/server/Program.cs
index 2ec0f48..80f8ebb 100644
--- a/server/Program.cs
+++ b/server/Program.cs
@@ -79,8 +79,6 @@ try
// Setup Program
MsgBus.Init();
- // if (app.Environment.IsDevelopment()) MsgBus.UDPServer.EnableDebugMode = true;
- MsgBus.UDPServer.EnableDebugMode = true;
// Router
// API Get
diff --git a/server/appsettings.json b/server/appsettings.json
index d035e31..92aa20f 100644
--- a/server/appsettings.json
+++ b/server/appsettings.json
@@ -60,6 +60,11 @@
"finalMinLevel": "Info",
"writeTo": "Console"
},
+ {
+ "logger": "server",
+ "finalMinLevel": "Trace",
+ "writeTo": "EachFile"
+ },
{
"logger": "server.*",
"finalMinLevel": "Trace",
diff --git a/server/src/Common.cs b/server/src/Common.cs
index 066c3af..4ba5513 100644
--- a/server/src/Common.cs
+++ b/server/src/Common.cs
@@ -50,14 +50,14 @@ namespace Common
{
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
{
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));
}
}
diff --git a/server/src/JtagController.cs b/server/src/JtagController.cs
index 28d065e..2502824 100644
--- a/server/src/JtagController.cs
+++ b/server/src/JtagController.cs
@@ -245,7 +245,7 @@ class Jtag
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send Address Package Failed!");
- // Wait for Ack
+ // Wait for Read Ack
if (!MsgBus.IsRunning)
throw new Exception("Message Bus not Working!");
@@ -261,7 +261,7 @@ class Jtag
if (retPackLen != 4)
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> RunCommand(uint devAddr, uint command)
@@ -279,6 +279,11 @@ class Jtag
opts.IsWrite = true;
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
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
if (!MsgBus.IsRunning)
throw new Exception("Message bus not working!");
@@ -288,10 +293,6 @@ class Jtag
if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful)
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
opts.IsWrite = false;
diff --git a/server/src/UdpServer.cs b/server/src/UdpServer.cs
index 8489f3d..d3d480d 100644
--- a/server/src/UdpServer.cs
+++ b/server/src/UdpServer.cs
@@ -1,7 +1,7 @@
using System.Net;
using System.Net.Sockets;
+using System.Runtime.CompilerServices;
using System.Text;
-using System.Threading.Tasks;
using DotNext;
using DotNext.Threading;
using Newtonsoft.Json;
@@ -30,6 +30,24 @@ public class UDPData
///
public required bool HasRead { get; set; }
+ ///
+ /// 深度拷贝对象
+ ///
+ /// UDPData
+ 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
+ };
+ }
+
///
/// 将UDP Data 转化为Json 格式字符串
///
@@ -56,11 +74,6 @@ public class UDPServer
private Dictionary> udpData = new Dictionary>();
private AsyncReaderWriterLock udpDataLock = new AsyncReaderWriterLock(1);
- ///
- /// 是否开启Debug模式
- ///
- public bool EnableDebugMode { get; set; }
-
///
/// Construct a udp server with fixed port
///
@@ -90,11 +103,18 @@ public class UDPServer
///
/// IP Address
/// Read and Write Wait for Milliseconds
+ /// 调用函数名称
+ /// 调用函数位置
/// UDP Data
- public Optional FindData(string ipAddr, int timeout = 1000)
+ public Optional FindData(
+ string ipAddr, int timeout = 1000,
+ [CallerMemberName] string callerName = "",
+ [CallerLineNumber] int callerLineNum = 0)
{
UDPData? data = null;
+ logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr} UDP Data");
+
var startTime = DateTime.Now;
var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout);
@@ -105,7 +125,7 @@ public class UDPServer
{
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
{
- data = udpData[ipAddr][0];
+ data = udpData[ipAddr][0].DeepClone();
udpData[ipAddr].RemoveAt(0);
logger.Debug($"Find UDP Data: {data.ToString()}");
break;
@@ -132,15 +152,22 @@ public class UDPServer
///
/// 目标IP地址
/// 超时时间
+ /// 调用函数名称
+ /// 调用函数位置
///
/// 异步Optional 数据包:
/// Optional 为空时,表明找不到数据;
/// Optional 存在时,为最先收到的数据
///
- public async ValueTask> FindDataAsync(string ipAddr, int timeout = 1000)
+ public async ValueTask> FindDataAsync(
+ string ipAddr, int timeout = 1000,
+ [CallerMemberName] string callerName = "",
+ [CallerLineNumber] int callerLineNum = 0)
{
UDPData? data = null;
+ logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr} UDP Data");
+
var startTime = DateTime.Now;
var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout);
@@ -151,7 +178,7 @@ public class UDPServer
{
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
{
- data = udpData[ipAddr][0];
+ data = udpData[ipAddr][0].DeepClone();
udpData[ipAddr].RemoveAt(0);
logger.Debug($"Find UDP Data: {data.ToString()}");
break;
@@ -215,7 +242,7 @@ public class UDPServer
}
///
- /// 异步等待读响应或写响应
+ /// 异步等待写响应
///
/// IP地址
/// UDP 端口
@@ -266,6 +293,7 @@ public class UDPServer
private void ReceiveHandler(IAsyncResult res)
{
+ logger.Trace("Enter handler");
var remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
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
- PrintData(RecordUDPData(bytes, remoteEP));
- }
+ // Handle Package
+ PrintData(RecordUDPData(bytes, remoteEP));
BEGIN_RECEIVE:
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)
{
var sendLen = listener.Send(buf, endPoint);
@@ -380,7 +354,9 @@ public class UDPServer
}
else
{
- udpData.Add(remoteAddress, new List([data]));
+ var list = new List();
+ list.Add(data);
+ udpData.Add(remoteAddress, list);
logger.Trace("Receive data from new client");
}
diff --git a/server/src/WebProtocol.cs b/server/src/WebProtocol.cs
index 8bce0fe..14c246e 100644
--- a/server/src/WebProtocol.cs
+++ b/server/src/WebProtocol.cs
@@ -478,7 +478,7 @@ namespace WebProtocol
{
if (bytes[0] != (byte)PackSign.RecvResp)
throw new ArgumentException(
- "The sign of bytes is not RecvData Package!",
+ "The sign of bytes is not RecvResp Package!",
nameof(bytes)
);
return new RecvRespPackage(bytes[1], bytes[2]);