socket传输对象,这篇很失败,请看BLOG中另外一篇

socket始终都只能传递byte数组,因为TCP/IP协议的原因。

如果需要传递一个对象,那么需要将这个对象序列化,然后就可以转换成byte数组进行传输了。

目前我只能传输struct,并且每个成员变量都不能是很复杂的类型,比如List<>类型的就不可以了,因为在获取其非托管大小的时候会发生异常的。

在获取非托管大小的时候不会发生异常的类型除了int、float、double、string等这些基本类型之外,还有array这种类型,其实int []、string []这些数组,都是继承自array 的。

 

首先定义序列化struct

[Serializable()] struct CC { public string[] a1; public string[] a2; }

 

其次转换对象为byte []

private static byte[] rawSerialize(object obj) { int rawsize = Marshal.SizeOf(obj); IntPtr buffer = Marshal.AllocHGlobal(rawsize); Marshal.StructureToPtr(obj, buffer, false); byte[] rawdatas = new byte[rawsize]; Marshal.Copy(buffer, rawdatas, 0, rawsize); Marshal.FreeHGlobal(buffer); return rawdatas; }

 

接收端将接收到的数组转换为类型

private static object rawDeserialize(byte[] rawdatas) { Type anytype = typeof(T); int rawsize = Marshal.SizeOf(anytype); if (rawsize > rawdatas.Length) return new object(); IntPtr buffer = Marshal.AllocHGlobal(rawsize); Marshal.Copy(rawdatas, 0, buffer, rawsize); object retobj = Marshal.PtrToStructure(buffer,anytype); Marshal.FreeHGlobal(buffer); return retobj; }   

 

socket接收的时候,接收端 :

recve是在接收的时候添加数据的,类型是List,每次接收到一个buffer的内容,就往recve添加一个。

(代码没有经过多行的测试,只是recve.Count==1的情况通过,因为我还没有测试过太大的对象的传输)

//如果判断接收已经结束,那么可以开始下面的代码 byte[] newrecv = new byte[0]; int offset = 0; for (int i = 0; i < recve.Count; i++) { Array.Resize(ref newrecv, recve[i].Length + newrecv.Length); Array.Copy(recve[i], 0, newrecv, offset, recve[i].Length); offset += recve[i].Length; } CC c = (CC)rawDeserialize(newrecv);

 

另外关于 int bytesRead = handler.EndReceive(ar); 的理解:

bytesRead 为0的情况是只有在对方close了socket之后。如果是大于0,说明对方还没有close,有可能还有数据传输过来。如果是小于0,可能是有网络异常,如果这句话直接异常,那么情况就是,你仍然在监听对方的消息,但是对方突然中断了(非正常退出)。

其实EndReceive就是socket的receive的异步的阻塞语句。只有当socket的接收完毕或者接收数据超过你传的buffer的大小之后,EndReceive才会释放阻塞,并且将得到的字节数量返回给bytesRead。

 

 using System.Runtime.InteropServices; 是 Marshal 的命名空间。

 

综述:

以上的代码实际上都是一无是处的,为什么?

如果是同一个进程中的通讯,你可以像上面那样些,但是如果是不同进程之间的话,你可以试试,绝对不能通过。

 

原因就是托管的资源问题。

socket传输很简单,我就不说了,而且也没有什么问题。

问题出现在转换对象为数组的时候,你建立的对象是一个托管对象,如果你没有使用正确的序列化,那么你得到的byte数组就是不正确的。

你将不正确的byte传输过去之后,再转换,你能转换成功吗?显然不能。

首先你要明白转换序列化的意义在什么地方。

转换序列化,其实就是找到托管资源的实际数据,然后将这些实际的数据转换为byte,这样转换的话,就是对的。

如果你不使用序列化,那么你的操作就是将托管资源转换为byte数组,那么这样转换的东西就不是真正的你需要的,你将这样的数据传输过去,是会引起不可预料的错误的。

 

具体这么样使用正确的序列化,有空的时候再研究吧。

你可能感兴趣的:(瞎扯)