| using System.Net.Sockets; |
| using System.Runtime.InteropServices; |
| |
| namespace Seer.SeerSocket; |
| public struct SeerMessageHead |
| { |
| public byte sync; |
| public byte version; |
| public ushort number; |
| public uint length; |
| 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 readonly TcpClient statusClient; |
| private readonly TcpClient? controlClient; |
| private readonly TcpClient? navClient; |
| private readonly TcpClient? configClient; |
| private readonly TcpClient? otherClient; |
| private bool isWrite=false; |
| |
| public SeerSocket(bool isWrite=false) |
| { |
| this.isWrite = isWrite; |
| if (isWrite) |
| { |
| |
| this.statusClient = new TcpClient("", 19204); |
| this.controlClient = new TcpClient("", 19205); |
| this.navClient = new TcpClient("", 19206); |
| this.configClient = new TcpClient("", 19207); |
| this.otherClient = new TcpClient("", 19210); |
| } |
| else |
| { |
| this.statusClient = new TcpClient("", 19204); |
| } |
| |
| } |
| |
| public string Send(ushort type, string msg = "", int port = 19204) |
| { |
| var msgBody = NormalStrToHexByte(msg); |
| var msgHead = CreateMsgHead(type, (uint)msgBody.Length); |
| if (port == 19204) |
| { |
| return this.SendRaw(msgHead, msgBody, statusClient); |
| } |
| else if (port == 19205 && this.isWrite) |
| { |
| return this.SendRaw(msgHead, msgBody, controlClient!); |
| } |
| else if (port == 19206 && this.isWrite) |
| { |
| return this.SendRaw(msgHead, msgBody, navClient!); |
| } |
| else if (port == 19207 && this.isWrite) |
| { |
| return this.SendRaw(msgHead, msgBody, configClient!); |
| } |
| else if (port == 19210 && this.isWrite) |
| { |
| return this.SendRaw(msgHead, msgBody, otherClient!); |
| } |
| return ""; |
| |
| } |
| |
| private string SendRaw(byte[] msgHead, byte[] msgBody, TcpClient client) |
| { |
| try |
| { |
| if (!client.Connected) 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; |
| } |
| |
| } |
| |
| |
| string resMsg = System.Text.Encoding.UTF8.GetString(datalist.ToArray()); |
| |
| return resMsg; |
| |
| } |
| catch (SocketException) |
| { |
| |
| return "fail"; |
| } |
| catch (IOException) |
| { |
| return "fail"; |
| } |
| } |
| |
| 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 = 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); |
| } |
| |
| } |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2022-02-14 css3 之结构性伪类选择器
2022-02-14 结构性伪类 :nth-child()
2022-02-14 后代选择器 子元素选择器 并集选择器 的区别
2022-02-14 css 高级选择器