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(); } } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2022-09-02 element plus自动导入 vue3 typescript ts2304 ElNotification
2022-09-02 vue props 联合类型定义 PropType的使用