finish web test api
This commit is contained in:
parent
f455af3589
commit
0da5b85173
|
@ -0,0 +1,13 @@
|
|||
root = true
|
||||
|
||||
# Default
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
|
||||
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
tab_width = 4
|
|
@ -27,6 +27,7 @@
|
|||
])
|
||||
nuget
|
||||
omnisharp-roslyn
|
||||
csharpier
|
||||
|
||||
# LSP
|
||||
typescript-language-server
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.Net;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
@ -22,22 +23,19 @@ if (app.Environment.IsDevelopment())
|
|||
});
|
||||
}
|
||||
|
||||
// Setup UDP Server
|
||||
var udpServer = new UDPServer(33000);
|
||||
udpServer.Start();
|
||||
|
||||
// Router
|
||||
app.MapGet("/", () => "Hello World!");
|
||||
app.MapPut("/api/SendString", Router.API.SendString);
|
||||
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
|
||||
app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
|
||||
|
||||
var thrdStartUdpServer = new ThreadStart(UDPServer.Start);
|
||||
var thrdUdpServer = new Thread(thrdStartUdpServer);
|
||||
thrdUdpServer.Start();
|
||||
Console.WriteLine("Start UDP Server");
|
||||
var thrdStartUdpClient = new ThreadStart(UDPClient.Start);
|
||||
var thrdUdpClient = new Thread(thrdStartUdpClient);
|
||||
thrdUdpClient.Start();
|
||||
Console.WriteLine("Start UDP Client");
|
||||
|
||||
|
||||
thrdUdpServer.Join();
|
||||
thrdUdpClient.Join();
|
||||
|
||||
// app.Run("http://localhost:5000");
|
||||
app.Run("http://localhost:5000");
|
||||
|
||||
// Close UDP Server
|
||||
Console.WriteLine("UDP Server is Closing now...");
|
||||
udpServer.Stop();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNext" Version="5.19.1" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.0.0" />
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
using DotNext;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class NumberProcessor
|
||||
{
|
||||
public static Result<byte[]> NumberToBytes(ulong num, uint length, bool isRightHigh = false)
|
||||
{
|
||||
if (length > 8)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Unsigned long number can't over 8 bytes(64 bits).",
|
||||
nameof(length)
|
||||
);
|
||||
}
|
||||
|
||||
var arr = new byte[length];
|
||||
|
||||
if (isRightHigh)
|
||||
{
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
arr[length - 1 - i] = Convert.ToByte((num >> (i << 3)) & (0xFF));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
arr[i] = Convert.ToByte((num >> (i << 3)) & (0xFF));
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static Result<ulong> BytesToNumber(byte[] bytes, bool isRightLeft = false)
|
||||
{
|
||||
if (bytes.Length > 8)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Unsigned long number can't over 8 bytes(64 bits).",
|
||||
nameof(bytes)
|
||||
);
|
||||
}
|
||||
|
||||
ulong num = 0;
|
||||
int len = bytes.Length;
|
||||
|
||||
if (isRightLeft)
|
||||
{
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
num += Convert.ToUInt64(bytes[len - 1 - i] << (i << 3));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
num += Convert.ToUInt64(bytes[i] << (i << 3));
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
public static Result<byte[]> StringToBytes(string str, int numBase = 16)
|
||||
{
|
||||
var len = str.Length;
|
||||
var bytesLen = len / 2;
|
||||
var bytes = new byte[bytesLen];
|
||||
|
||||
for (var i = 0; i < bytesLen; i++)
|
||||
{
|
||||
bytes[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System.Net;
|
||||
using Common;
|
||||
|
||||
namespace Router
|
||||
{
|
||||
class API
|
||||
{
|
||||
public static void SendString(string address, int port, string text)
|
||||
{
|
||||
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
|
||||
UDPClientPool.AsyncSendString(endPoint, [text]);
|
||||
}
|
||||
|
||||
public static void SendAddrPackage(
|
||||
string address,
|
||||
int port,
|
||||
WebProtocol.BurstType burstType,
|
||||
byte commandID,
|
||||
bool isWrite,
|
||||
byte burstLength,
|
||||
UInt32 devAddress)
|
||||
{
|
||||
WebProtocol.SendAddrPackOptions opts;
|
||||
opts.burstType = burstType;
|
||||
opts.commandID = commandID;
|
||||
opts.isWrite = isWrite;
|
||||
opts.burstLength = burstLength;
|
||||
opts.address = devAddress;
|
||||
|
||||
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
|
||||
UDPClientPool.SendAddrPack(endPoint, new WebProtocol.SendAddrPackage(opts));
|
||||
}
|
||||
|
||||
public static void SendDataPackage(string address, int port, string data)
|
||||
{
|
||||
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
|
||||
UDPClientPool.SendDataPack(endPoint,
|
||||
new WebProtocol.SendDataPackage(NumberProcessor.StringToBytes(data).Value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,6 +31,28 @@ class UDPClientPool
|
|||
await Task.Run(() => { SendBytes(endPoint, buf); });
|
||||
}
|
||||
|
||||
public static void SendAddrPack(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg)
|
||||
{
|
||||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
socket.SendTo(pkg.ToBytes(), endPoint);
|
||||
}
|
||||
|
||||
public async static void AsyncSendAddrPack(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg)
|
||||
{
|
||||
await Task.Run(() => { SendAddrPack(endPoint, pkg); });
|
||||
}
|
||||
|
||||
public static void SendDataPack(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg)
|
||||
{
|
||||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
socket.SendTo(pkg.ToBytes(), endPoint);
|
||||
}
|
||||
|
||||
public async static void AsyncSendDataPack(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg)
|
||||
{
|
||||
await Task.Run(() => { SendDataPack(endPoint, pkg); });
|
||||
}
|
||||
|
||||
public static void SendLocalHost(int port, string[] stringArray)
|
||||
{
|
||||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
|
|
|
@ -7,57 +7,87 @@ public class UDPServer
|
|||
private int listenPort;
|
||||
private UdpClient listener;
|
||||
private IPEndPoint groupEP;
|
||||
private Thread thrd;
|
||||
private bool isRunning;
|
||||
|
||||
|
||||
|
||||
public UDPServer(int port)
|
||||
{
|
||||
// Construction
|
||||
listenPort = port;
|
||||
listener = new UdpClient(listenPort);
|
||||
groupEP = new IPEndPoint(IPAddress.Any, listenPort);
|
||||
|
||||
// New Thread
|
||||
var thrdStart = new ThreadStart(ReceiveHandler);
|
||||
thrd = new Thread(thrdStart);
|
||||
}
|
||||
|
||||
private void ReceiveHandler()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (isRunning)
|
||||
{
|
||||
byte[] bytes = listener.Receive(ref groupEP);
|
||||
listener = new UdpClient(listenPort);
|
||||
groupEP = new IPEndPoint(IPAddress.Any, listenPort);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
throw new ArgumentException(
|
||||
$"Not currect port num: {port}",
|
||||
nameof(port)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Received broadcast from {groupEP} :");
|
||||
Console.WriteLine($" {Encoding.ASCII.GetString(bytes, 0, bytes.Length)}");
|
||||
}
|
||||
}
|
||||
catch (SocketException e)
|
||||
private void ReceiveHandler(IAsyncResult res)
|
||||
{
|
||||
var remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
|
||||
byte[] bytes = listener.EndReceive(res, ref remoteEP);
|
||||
|
||||
var sign = bytes[0];
|
||||
|
||||
string recvData;
|
||||
if (sign == (byte)WebProtocol.PackSign.SendAddr)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
var resData = WebProtocol.SendAddrPackage.FromBytes(bytes);
|
||||
if (resData.IsSuccessful)
|
||||
recvData = resData.Value.ToString();
|
||||
else
|
||||
recvData = resData.Error.ToString();
|
||||
}
|
||||
finally
|
||||
else if (sign == (byte)WebProtocol.PackSign.SendData)
|
||||
{
|
||||
listener.Close();
|
||||
recvData = "";
|
||||
}
|
||||
else if (sign == (byte)WebProtocol.PackSign.RecvData)
|
||||
{
|
||||
recvData = "";
|
||||
}
|
||||
else if (sign == (byte)WebProtocol.PackSign.RecvResp)
|
||||
{
|
||||
recvData = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
string remoteStr = (remoteEP is null) ? "Unknown" : $"{remoteEP.Address.ToString()}:{remoteEP.Port.ToString()}";
|
||||
Console.WriteLine($"Receive Data from {remoteStr} at {DateTime.Now.ToString()}:");
|
||||
Console.WriteLine($"Original Data: {BitConverter.ToString(bytes).Replace("-", " ")}");
|
||||
if (recvData.Length != 0) Console.WriteLine(recvData);
|
||||
Console.WriteLine();
|
||||
|
||||
listener.BeginReceive(new AsyncCallback(ReceiveHandler), null);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
isRunning = true;
|
||||
thrd.Start();
|
||||
try
|
||||
{
|
||||
listener.BeginReceive(new AsyncCallback(ReceiveHandler), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
isRunning = false;
|
||||
thrd.Join();
|
||||
listener.Close();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using DotNext;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace WebProtocol
|
||||
{
|
||||
|
||||
public enum PackSign
|
||||
{
|
||||
SendAddr = 0x00,
|
||||
|
@ -15,36 +17,179 @@ namespace WebProtocol
|
|||
FixedBurst = 0b01,
|
||||
}
|
||||
|
||||
public struct SendAddrPackOptions
|
||||
{
|
||||
public BurstType burstType;
|
||||
public byte commandID;
|
||||
public bool isWrite;
|
||||
public byte burstLength;
|
||||
public UInt32 address;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
public struct RecvPackOptions
|
||||
{
|
||||
public byte commandID;
|
||||
public bool isSuccess;
|
||||
}
|
||||
|
||||
public struct SendAddrPackage
|
||||
{
|
||||
readonly byte Sign = (byte)PackSign.SendAddr;
|
||||
readonly byte sign = (byte)PackSign.SendAddr;
|
||||
readonly byte commandType;
|
||||
readonly byte burstLength;
|
||||
readonly byte _reserved;
|
||||
readonly byte _reserved = 0;
|
||||
readonly UInt32 address;
|
||||
|
||||
public SendAddrPackage(SendAddrPackOptions opts)
|
||||
{
|
||||
byte byteBurstType = Convert.ToByte((byte)opts.burstType << 5);
|
||||
byte byteCommandID = Convert.ToByte((opts.commandID & 0x03) << 3);
|
||||
byte byteIsWrite = (opts.isWrite ? (byte)0x01 : (byte)0x00);
|
||||
this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite);
|
||||
this.burstLength = opts.burstLength;
|
||||
this.address = opts.address;
|
||||
}
|
||||
|
||||
public SendAddrPackage(BurstType burstType, byte commandID, bool isWrite)
|
||||
{
|
||||
commandType = (
|
||||
((byte)burstType << 5) |
|
||||
((commandID & (byte)0x03) << 3) |
|
||||
(isWrite ? (byte)0x01 : (byte)0x00)
|
||||
);
|
||||
byte byteBurstType = Convert.ToByte((byte)burstType << 5);
|
||||
byte byteCommandID = Convert.ToByte((commandID & 0x03) << 3);
|
||||
byte byteIsWrite = (isWrite ? (byte)0x01 : (byte)0x00);
|
||||
this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite);
|
||||
}
|
||||
|
||||
public void toBytes()
|
||||
public SendAddrPackage(byte commandType, byte burstLength, UInt32 address)
|
||||
{
|
||||
this.commandType = commandType;
|
||||
this.burstLength = burstLength;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
var arr = new byte[8];
|
||||
arr[0] = sign;
|
||||
arr[1] = commandType;
|
||||
arr[2] = burstLength;
|
||||
arr[3] = _reserved;
|
||||
|
||||
var bytesAddr = Common.NumberProcessor.NumberToBytes(address, 4).Value;
|
||||
Array.Copy(bytesAddr, 0, arr, 4, bytesAddr.Length);
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
SendAddrPackOptions opts;
|
||||
opts.burstType = (BurstType)(commandType >> 5);
|
||||
opts.commandID = Convert.ToByte((commandType >> 3) & 0b0011);
|
||||
opts.isWrite = Convert.ToBoolean(commandType & 0x01);
|
||||
opts.burstLength = burstLength;
|
||||
opts.address = address;
|
||||
|
||||
return JsonConvert.SerializeObject(opts);
|
||||
}
|
||||
|
||||
public static Result<SendAddrPackage> FromBytes(byte[] bytes, bool checkSign = true)
|
||||
{
|
||||
if (bytes.Length != 8)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Bytes are not equal to 8 bytes.",
|
||||
nameof(bytes)
|
||||
);
|
||||
}
|
||||
|
||||
if (checkSign && bytes[0] != (byte)PackSign.SendAddr)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"The sign of bytes is not SendAddr Package, but you can disable it by set checkSign false.",
|
||||
nameof(bytes)
|
||||
);
|
||||
}
|
||||
|
||||
var address = Common.NumberProcessor.BytesToNumber(bytes[4..]).Value;
|
||||
return new SendAddrPackage(bytes[1], bytes[2], Convert.ToUInt32(address));
|
||||
}
|
||||
}
|
||||
|
||||
public struct RecvRackage
|
||||
public struct SendDataPackage
|
||||
{
|
||||
readonly byte sign = (byte)PackSign.SendData;
|
||||
readonly byte[] _reserved = new byte[3];
|
||||
readonly byte[] bodyData;
|
||||
|
||||
public void toBytes()
|
||||
public SendDataPackage(byte[] bodyData)
|
||||
{
|
||||
this.bodyData = bodyData;
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
var bodyDataLen = bodyData.Length;
|
||||
var arr = new byte[4 + bodyDataLen];
|
||||
|
||||
arr[0] = sign;
|
||||
|
||||
Array.Copy(bodyData, 0, arr, 4, bodyDataLen);
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public struct RecvDataPackage
|
||||
{
|
||||
readonly byte sign = (byte)PackSign.RecvData;
|
||||
readonly byte commandID;
|
||||
readonly byte resp;
|
||||
readonly byte _reserved = 0;
|
||||
readonly byte[] bodyData;
|
||||
|
||||
public RecvDataPackage(byte commandID, byte resp, byte[] bodyData)
|
||||
{
|
||||
this.commandID = commandID;
|
||||
this.resp = resp;
|
||||
this.bodyData = bodyData;
|
||||
}
|
||||
|
||||
public RecvPackOptions Options()
|
||||
{
|
||||
RecvPackOptions opts;
|
||||
opts.commandID = commandID;
|
||||
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false);
|
||||
|
||||
return opts;
|
||||
}
|
||||
}
|
||||
|
||||
public struct RecvRespPackage
|
||||
{
|
||||
readonly byte sign = (byte)PackSign.RecvResp;
|
||||
readonly byte commandID;
|
||||
readonly byte resp;
|
||||
readonly byte _reserved = 0;
|
||||
|
||||
public RecvRespPackage(byte commandID, byte resp)
|
||||
{
|
||||
this.commandID = commandID;
|
||||
this.resp = resp;
|
||||
}
|
||||
|
||||
public RecvPackOptions Options()
|
||||
{
|
||||
RecvPackOptions opts;
|
||||
opts.commandID = commandID;
|
||||
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false);
|
||||
|
||||
return opts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped>
|
||||
@import "@/assets/main.css"
|
||||
@import "@/assets/main.css";
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue