Dotnet.Seer/SeerSocket.cs
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Seer.SeerSocket;
public struct SeerMessageHead
{
public byte sync; // 0x5A
public byte version; // 0x01
public ushort number; // 0-65536
public uint length; // 数据区长度,json序列化数据长度
public ushort type; // 报文的类型
#pragma warning disable 0414 //禁用警告
#pragma warning disable 0169 //禁用警告
private readonly byte ref0; //保留
private readonly byte ref1; //保留
private readonly byte ref2; //保留
private readonly byte ref3; //保留
private readonly byte ref4; //保留
private readonly byte ref5; //保留
#pragma warning restore 0414 //恢复警告
#pragma warning restore 0169 //恢复警告
public SeerMessageHead()
{
this.sync = 0x5A;
this.version = 0x01;
this.number = 0x0001;
}
public SeerMessageHead(ushort type)
{
this.type = type;
}
public readonly byte[] ToBytes()
{
int size = Marshal.SizeOf(this);
byte[] bytes = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(this, ptr, true);
Marshal.Copy(ptr, bytes, 0, size);
Marshal.FreeHGlobal(ptr);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes, 2, 2);
Array.Reverse(bytes, 4, 4);
Array.Reverse(bytes, 8, 2);
}
return bytes;
}
};
public class SeerSocket
{
private const string IpAddress = "127.0.0.1";
private readonly Dictionary<int, TcpClient> clients;
public SeerSocket(bool onlyRead = true)
{
this.clients = new Dictionary<int, TcpClient>
{
{ 19204, new TcpClient(IpAddress, 19204) }
};
if (onlyRead) return;
this.clients.Add(19205, new TcpClient(IpAddress, 19205));
this.clients.Add(19206, new TcpClient(IpAddress, 19206));
this.clients.Add(19207, new TcpClient(IpAddress, 19207));
this.clients.Add(19210, new TcpClient(IpAddress, 19210));
}
// 使用键来访问特定的TcpClient对象
private TcpClient GetClient(int port)
{
return clients[port];
}
public string Send(ushort type, string msg = "", int port = 19204)
{
var msgBody = NormalStrToHexByte(msg);
var msgHead = CreateMsgHead(type, (uint)msgBody.Length);
var response = this.SendRaw(msgHead, msgBody, port);
return response;
}
private string SendRaw(byte[] msgHead, byte[] msgBody, int port)
{
try
{
TcpClient client = this.GetClient(port);
if (!client.Connected)
{
this.clients[port] = new TcpClient(IpAddress, port);
Console.WriteLine($"{IpAddress}:{port}:断开连接");
return "fail";
}
NetworkStream serverStream = client.GetStream();
serverStream.Write(msgHead, 0, msgHead.Length);
serverStream.Write(msgBody, 0, msgBody.Length);
serverStream.Flush();
byte[] inStream = new byte[16];
while (16 != serverStream.Read(inStream, 0, 16))
{
Thread.Sleep(20);
}
var recv_head = BytesToStructure<SeerMessageHead>(inStream);
byte[] recvbyte = BitConverter.GetBytes(recv_head.length);
Array.Reverse(recvbyte);
// 获取数据区的长度
var dsize = BitConverter.ToUInt32(recvbyte, 0);
const int bufferSize = 512;
List<byte> datalist = new List<byte>();
int count = 0;
while (true)
{
byte[] buffer = new byte[bufferSize];
int readSize = serverStream.Read(buffer, 0, bufferSize);
count += readSize;
datalist.AddRange(buffer);
if (count == dsize)
{
break;
}
}
// var content = BitConverter.ToString(SeerMessageHeadToBytes(recv_head)).Replace("-", " ");
// Console.WriteLine(content);
string resMsg = System.Text.Encoding.UTF8.GetString(datalist.ToArray());
return resMsg;
}
catch (SocketException)
{
return "fail";
}
catch (IOException)
{
return "fail";
}
}
public void CloseAll(){
foreach(var client in this.clients.Values){
client.Close();
}
}
private T BytesToStructure<T>(byte[] bytesBuffer)
{
if (bytesBuffer.Length < Marshal.SizeOf(typeof(T)))
{
throw new ArgumentException("size error");
}
nint bufferHandler = Marshal.AllocHGlobal(bytesBuffer.Length);
for (int index = 0; index < bytesBuffer.Length; index++)
{
Marshal.WriteByte(bufferHandler, index, bytesBuffer[index]);
}
// T? structObject = (T)Marshal.PtrToStructure(bufferHandler, typeof(T));
T? structObject = Marshal.PtrToStructure<T>(bufferHandler);
Marshal.FreeHGlobal(bufferHandler);
if (structObject == null)
{
throw new InvalidOperationException("Failed to convert bytes to structure.");
}
return structObject!;
}
private byte[] NormalStrToHexByte(string str)
{
byte[] result = new byte[str.Length];
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
for (int i = 0; i < buffer.Length; i++)
{
result[i] = Convert.ToByte(buffer[i].ToString("X2"), 16);
}
return result;
}
private byte[] CreateMsgHead(ushort type, uint msgLen)
{
var msgHead = new SeerMessageHead
{
type = type,
length = msgLen
};
return msgHead.ToBytes();
}
public static void PrintBytes(byte[] bytes)
{
foreach (byte b in bytes)
{
Console.Write("{0:X2} ", b);
}
}
}
Dotnet.Seer/Dotnet.Seer.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Dotnet.Seer/Program.cs
using Seer.SeerSocket;
var seer = new SeerSocket();
while (true)
{
var msg = seer.Send(0x0410, """{"motor_names": ["motor1"]}""", 19204);
Console.WriteLine(msg);
Thread.Sleep(2000);
}
标签:return,socket,ip,tcp,Marshal,private,new,byte,public
From: https://www.cnblogs.com/zhuoss/p/18016139