SeerAGV_2/SeerMessage.cs
using System.Reflection;
using System.Runtime.InteropServices;
namespace SeerAGV
{
public struct SeerMessageHead
{
public byte sync;
public byte version;
public ushort number;
public uint length;
public ushort type;
#pragma warning disable CS0169 // 禁用 CS0169 警告
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 CS0169 // 启用 CS0169 警告
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 struct SeerMessage
{
public byte[] head;
public byte[] body;
public SeerMessage(SeerMessageHead head, string body)
{
this.body = SetBody(body);
// head中的lenght是body的长度
head.length = (uint)this.body.Length;
this.head = head.ToBytes();
}
public readonly int Length()
{
return body.Length + Marshal.SizeOf(head);
}
private static byte[] SetBody(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;
}
}
}
SeerAGV_2/SeerAGV.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
SeerAGV_2/Program.cs
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace SeerAGV
{
/// <summary>
///
/// </summary>
public class SeerSocket
{
/// <summary>
/// 该方法接受一个十六进制字符串作为参数,并返回一个字节数组。
/// 它首先使用 `Replace` 方法删除字符串中的所有空格,
/// 然后检查字符串的长度是否为偶数。如果不是,它会在字符串末尾添加一个空格。
/// 接下来,它创建一个新的字节数组,并使用 `for` 循环遍历字符串中的每两个字符。
/// 在循环中,它使用 `Substring` 方法获取当前两个字符,然后使用 `Convert.ToByte` 方法将它们转换为一个字节,并将该字节存储在字节数组中。
/// 最后,它返回字节数组。
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
private static byte[] HexStrTobyte(string hexString)
{
hexString = hexString.Replace(" ", "");
if (hexString.Length % 2 != 0)
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
{
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
}
return returnBytes;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytesBuffer"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static 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!;
}
/// <summary>
///该方法接受一个字符串作为参数,并返回一个字节数组。
///它首先创建一个新的字节数组,其长度与输入字符串的长度相同。
///然后,它使用 `System.Text.Encoding.UTF8.GetBytes` 方法将输入字符串转换为 UTF-8 编码的字节数组。
///接下来,它使用 `for` 循环遍历该字节数组中的每个字节。
///在循环中,它使用 `ToString` 方法将当前字节转换为十六进制字符串,并使用 `Convert.ToByte` 方法将该字符串转换为字节,并将该字节存储在结果字节数组中。
///最后,它返回结果字节数组。希望这对您有所帮助!
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static 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;
}
public static byte[] SeerMessageHeadToBytes(SeerMessageHead msg)
{
var hsize = Marshal.SizeOf(msg);
byte[] bytes = new byte[hsize];
nint structPtr = Marshal.AllocHGlobal(hsize);
Marshal.StructureToPtr(msg, structPtr, false);
Marshal.Copy(structPtr, bytes, 0, hsize);
Marshal.FreeHGlobal(structPtr);
return bytes;
}
public static void Send()
{
try
{
// 创建tcp连接
var client = new TcpClient("127.0.0.1", 19204);
if (client.Connected)
{
NetworkStream serverStream = client.GetStream();
// 创建一些变量
var seerMsg = new SeerMessage(new SeerMessageHead
{
sync = 0x5a,
version = 0x01,
number = 0x0001,
type = 2002,
}, $"{{\"x\":10.0,\"y\":3.0,\"angle\":0}}");
serverStream.Write(seerMsg.head, 0, seerMsg.head.Length);
serverStream.Write(seerMsg.body, 0, seerMsg.body.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;
var 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;
}
Thread.Sleep(10);
}
var content = BitConverter.ToString(SeerMessageHeadToBytes(recv_head)).Replace("-", " ");//normalStrToHexStr(Encoding.UTF8.GetString(seerMessageHeadToBytes(recv_head)));
Console.WriteLine(content);
string str = System.Text.Encoding.UTF8.GetString(datalist.ToArray());
client.Close();
}
}
catch (SocketException)
{
}
catch (IOException)
{
}
}
}
/// <summary>
/// 将socket封装成一个类
/// </summary>
public class SocketClient
{
// 定义一些私有字段,用于存储客户端、网络流和缓冲区大小等信息
private TcpClient client;
private NetworkStream stream;
private const int bufferSize = 512;
// 定义一个构造函数,用于创建一个socket客户端,并连接到指定的服务器地址和端口
public SocketClient(string address, int port)
{
client = new TcpClient(address, port);
if (client.Connected)
{
stream = client.GetStream();
}
else
{
throw new Exception("Failed to connect to the server.");
}
}
// 定义一个Send方法,用于发送一个SeerMessage类型的结构体到服务器
public void Send(SeerMessage message)
{
if (stream != null)
{
stream.Write(message.head, 0, message.head.Length);
stream.Write(message.body, 0, message.body.Length);
stream.Flush();
}
else
{
throw new Exception("The network stream is null.");
}
}
// 定义一个Receive方法,用于接收服务器返回的一个SeerMessage类型的结构体
public string Receive()
{
if (stream != null)
{
// 接收消息头
byte[] headBytes = new byte[16];
while (16 != stream.Read(headBytes, 0, 16))
{
Thread.Sleep(20);
}
var head = BytesToStructure<SeerMessageHead>(headBytes);
// 接收消息体
byte[] lengthBytes = BitConverter.GetBytes(head.length);
Array.Reverse(lengthBytes);
var bodyLength = BitConverter.ToUInt32(lengthBytes, 0);
var bodyList = new List<byte>();
int count = 0;
while (true)
{
byte[] buffer = new byte[bufferSize];
int readSize = stream.Read(buffer, 0, bufferSize);
count += readSize;
bodyList.AddRange(buffer);
if (count == bodyLength)
{
break;
}
Thread.Sleep(10);
}
var body = bodyList.ToArray();
// 返回消息
return BitConverter.ToString(body);
}
else
{
throw new Exception("The network stream is null.");
}
}
public static 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!;
}
}
class Program
{
static void Main(string[] args)
{
var myObject = new SeerSocket();
SeerSocket.Send();
}
}
}
标签:小端,head,c#,public,Length,序列,new,byte,Marshal
From: https://www.cnblogs.com/zhuoss/p/17673722.html