C# UDP接收结构体数据类型-----只能读取第一个字段的问题
来源:互联网 发布:wordpress整站源码 编辑:程序博客网 时间:2024/06/02 10:12
在C#的UDP接收嵌入式设备端发送的结构体数据时,经过
//声明一个SDK_MSG_DEVICEINFO的结构体
[Serializable] // 指示可序列化
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
//[StructLayout(LayoutKind.Sequential, Pack = 1)] // 按1字节对齐
public struct SDK_MSG_DEVICEINFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] // 声明一个字符数组,大小为64
public string hardware_ver; //硬件版本
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] // 声明一个字符数组,大小为20
public string szMacAddr; //MAC STRING
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
public string szUID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
public string szPwd;
};
///发送的时候先要把结构转换成字节数组
/// 将结构转换为字节数组
/// 结构对象
/// 字节数组
public byte[] StructToBytes(object obj)
{
//得到结构体的大小
int size = Marshal.SizeOf(obj);
//创建byte数组
byte[] bytes = new byte[size];
//分配结构体大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将结构体拷到分配好的内存空间
Marshal.StructureToPtr(obj, structPtr, false);
//从内存空间拷到byte数组
Marshal.Copy(structPtr, bytes, 0, size);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回byte数组
return bytes;
}
//接收的时候需要把字节数组转换成结构
/// byte数组转结构
///
/// byte数组
/// 结构类型
/// 转换后的结构
public object BytesToStruct(byte[] bytes, Type type)
{
//得到结构的大小
int size = Marshal.SizeOf(type);
//Log(size.ToString(), 1);
//byte数组长度小于结构的大小
if (size > bytes.Length)
{
//返回空
return null;
}
//分配结构大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构
object obj = Marshal.PtrToStructure(structPtr, type);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回结构
return obj;
}
void RecvThread()
{
EndPoint ep = (EndPoint)endpoint;
while (true)
{
byte[] buf = new byte[1024];
SDK_MSG_DEVICEINFO deviceinfo = new SDK_MSG_DEVICEINFO();
int count = sock.ReceiveFrom(buf, ref ep);
Console.WriteLine(">>>>>ip>>" + (ep as IPEndPoint).Address.ToString() +">>>>>port>>>"+ (ep as IPEndPoint).Port.ToString()); // 发送方的IP地址
deviceinfo = (SDK_MSG_DEVICEINFO)this.BytesToStruct(buf, typeof(SDK_MSG_DEVICEINFO));
if (deviceinfo.szUID.Length > 0)
{
if (udpIPaddr.Count < UDP_MAX_VALUE)
{
String ipstr = (ep as IPEndPoint).Address.ToString();
//判断是否List中已经有搜索到的IP,如有跳过
if (udpIPaddr.Contains(ipstr) == false)
{
udpIPaddr.Add(ipstr);
Console.WriteLine("deviceinfo.szUID " + deviceinfo.szUID.ToString());
Console.WriteLine("deviceinfo.szPwd " + deviceinfo.szPwd.ToString());
Console.WriteLine("deviceinfo.szMacAddr " + deviceinfo.szMacAddr.ToString());
Console.WriteLine("deviceinfo.hardware_ver " + deviceinfo.hardware_ver.ToString());
sdkMsgDeviceInfo.Add(deviceinfo);
}
}
}
}
}
int count = sock.ReceiveFrom(buf, ref ep)接收到的数据长度是正确的,但是打印显示只能获取第一个字段deviceinfo.hardware_ver。
问题解决办法:
将结构体的按8的倍数对齐即可
//声明一个SDK_MSG_DEVICEINFO的结构体
[Serializable] // 指示可序列化
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SDK_MSG_DEVICEINFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)] // 声明一个字符数组,大小为24
public string szMacAddr; //MAC STRING
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
public string szUID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
public string szPwd;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] // 声明一个字符数组,大小为64
public string hardware_ver; //硬件版本
};
- C# UDP接收结构体数据类型-----只能读取第一个字段的问题
- c#的 UDP接收
- 解决Oracle的Char只能读取第一个字符
- DDDW重复行只能选择第一个的问题
- Jquery、JavaScript 只能替换第一个字符串的问题
- FusionCharts free中的setDataURL只能接收第一个参数??
- 大部分游戏数据库引擎只能读取存储过程的第一个记录集
- udp 发送和接收结构体数据
- c#读取Excel的第一个Sheet表
- c#读取Excel的第一个Sheet表
- c#读取Excel的第一个Sheet表
- C#读取Oracle的Long Row字段值的问题
- Flex中实现多个文件上传时发生只能上传第一个文件的问题
- UDP 协议 C# UdpClient乱序接收数据包丢失的问题 Socket ReceiveBufferSize
- 关于hibernate查询sqlserver时char类型只能取第一个字符的问题
- UDP 接收问题
- HttpServetRequest读取body只能一次的问题
- 第一个C#程序的坑爹问题
- IOS测试你需要知道哪些特性?
- Mybatis:逆向生成工具,DATE,TIMESTAMP的有关问题
- Linux内核移植 part1:Exynos 4412 uboot 调试
- ChannelHandler的用法
- Gson的简单使用方法
- C# UDP接收结构体数据类型-----只能读取第一个字段的问题
- 修改 K8s kubelet启动参数
- PHP 不同地图坐标系经纬度转换 GCj02 WGS84 BD-09
- netty 对象序列化传输示例
- C语言获取当前系统时间
- Kibana 可视化监控报警插件 KAAE 的介绍与使用
- JSP页面在被访问的时候的执行过程
- 作用域链&原型链
- JS中运算符i++与++i的详细分析