在网络传输上常常会听到字节流传输数据个词,刚好最近公司接到一个利用UDP传输字节流的传输数据的的项目,他们公司传输的是一个结构体的的字节流数据,我们需要对传输过来的字节流的的接收和进行数据的转化。
这里我们就要了解什么事字节,字节是一种计算机的数据存储的计量单位,也白表示一些计算机编程语言中的数据类型以及语言字符。这样说可能很书面化的答案,在我们用电脑的时候常会说,1KB,1GB,1TB等,这里B就表示的Byte也就是我们常说的字节。
下面是百度的数据存储转化对应表:
那么如果我想传输结构体的数据的时候,就要涉及到对字节计算,只有在结构体和字节流的长度都正确的情况下转化才能正常完成。那么我们来简单的计算一下下面的字节大概是多少吧~
public struct TestStruct
{
public int newint;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string newstr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public int[] test;
}
上面的代码的总共32个字节,那么怎么计算出来的呢?
newint占用4个字节
newstr占用20个字节
test数组则是8个字节
有人肯定会问string为什么会20个字节是,test为什么是8个字节呢?这里原因很简单,我对结构体的string的字节长度进行了限制上面的 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]这句话就是对string长度进行了限制,同理int数字也是限制了长度2个。
这里肯定有人会问为啥要限制string和数字长度呢?
因为在数据传输中结构体转化byte中string会根据你真实的数据来判断是否要添加string的长度,导致客户端无法判断string正确占用多少字节,就会导致数据转化时候出问题了
int[]是应为这个原因导致数据转化出现错误和数据丢失的问题。
那么我们怎么验证结构体的字节计算时正确的呢?mscorlib.dll库为我们提供了Marshal法来计算结构体的字节大小方法,方法如图所示:
我们去验证一下字节数究竟对不对,下图为我断点调试的结果,如果所示:
结构体中字节数占用的32个字节,然后我申请一个句柄来存储结构体的数据,然后将句柄中的数据赋值给字节数组,然后是放句柄的就就可以了~
这样就达到了数据字节流的转化了。
那么传出过来的数据是字节流,也就表示客户端肯定需要转化数据后才能使用其结构体的数据,Marshal方法也为我们提供了byte数组转化方法了,这里我们只要调用就可以转化成结构体。
这里要注意的是客户端的结构体一定顺序一定要和服务端的一致不然转化数据的时候就会出问题的,还有的是一定要注意结构体的字节一定要和服务端一致,不然转化一定会出现数据错误甚至直接报错栈溢出等。
方法和结构体转化byte型一样,都是通过句柄进行中间的转化,通过句柄来转化结构体。代码如下图所示:
这里通过泛型来判断结构体,同样在进入转化的时候,我们先去判断结构体的字节是否和需要转化的字节数组对应的上。
最后看看调试转化后的效果,效果如下图所示:
但是我公司接到的数据并不是10进制的数据,而是16进制的,在byte数组里面可以详细看到数据是10进制的,这里需要用到10进制转16进制的方法。这里只要知道10怎么转化16进制就可以解决这个问题了。有时间我会将这个原理写出来。
这里要感谢天下的博文:点击打开链接
还有xiaobai1593的转载博文:点击打开链接 原文的作者并没有找到,但是还是非常感谢!!
如果有兴趣的孩子还在可以去试试将客户端的机构体换换顺序,你会发现意想不到的问题的~