C# memorystream复制到网络流问题
我这里的代码有问题C# memorystream复制到网络流问题,c#,networking,memorystream,networkstream,binaryformatter,C#,Networking,Memorystream,Networkstream,Binaryformatter,我这里的代码有问题 using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms,SerializableClassOfDoom); ms.Position = 0; byte[] messsize = BitConverter.GetBytes(ms.Length); ms.Write(messsize,
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms,SerializableClassOfDoom);
ms.Position = 0;
byte[] messsize = BitConverter.GetBytes(ms.Length);
ms.Write(messsize, 0, messsize.Length);
NetworkStream ns = Sock.GetStream();
ms.CopyTo(ns);
//ms.Close();
}
我不知道这里发生了什么,或者为什么它不起作用。它似乎没有复制,或者它关闭了网络流,或者其他什么
很抱歉,我已经试过调试它了,但是如果有人能在这里看到任何明显的问题,我将不胜感激
顺便说一句,类序列化很好,MemoryStream包含数据,但是出于某种原因,执行ms.CopyTo(ns)似乎不起作用
本质上,我想做的是将该类序列化到网络流,并在其前面设置序列化数据的大小。如果有人有更好的方法让我知道 在调用CopyTo(使用ms.Seek(0,SeekOrigin.Start))之前,可能需要将内存流倒回到开始处。我没有看到真正的问题,但我在这里看到了一些重构问题 试用
Stream.Flush()
Stream.Close()
在完成任何流之前
还可以用类似这样的try catch
语句来包围它,以确保即使出现异常也能关闭和刷新
Stream s = new Stream();
try{
s.Write();
}catch(Exception ex){
//Oh god, we are doomed!
}finally{
s.Flush();
s.Close();
}
你的代码看起来像
NetworkStream ns = null;
using (MemoryStream ms = new MemoryStream())
{
try{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms,SerializableClassOfDoom);
ms.Position = 0;
byte[] messsize = BitConverter.GetBytes(ms.Length);
ms.Write(messsize, 0, messsize.Length);
ns = Sock.GetStream();
ms.CopyTo(ns);
//ms.Close();
}catch(Exception ex){
throw;
}finally{
ms.Flush();
if(ns != null)
ns.Flush();
ms.Close();
}
}
在此之后,您应该能够找到您的问题。您在错误的时间重置了流位置 在本例中,您将“长度”写入流的开头 以下方面应起作用:
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms,SerializableClassOfDoom);
byte[] messsize = BitConverter.GetBytes(ms.Length);
ms.Write(messsize, 0, messsize.Length);
ms.Position = 0;
NetworkStream ns = Sock.GetStream();
ms.CopyTo(ns);
}
更新:
要将“长度”写入开头,请使用临时流/字节[]
例如:
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms,SerializableClassOfDoom);
byte[] data = ms.ToArray();
byte[] messsize = BitConverter.GetBytes(ms.Length);
ms.Position = 0;
ms.Write(messsize, 0, messsize.Length);
ms.Write(data, 0, data.Length);
ms.Position = 0; // again!
NetworkStream ns = Sock.GetStream();
ms.CopyTo(ns);
}
更新2:
更有效的方法
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms,SerializableClassOfDoom);
byte[] messsize = BitConverter.GetBytes(ms.Length);
NetworkStream ns = Sock.GetStream();
ns.Write(messsize, 0, messsize.Length);
ms.Position = 0; // not sure if needed, doc for CopyTo unclear
ms.CopyTo(ns);
}
我的猜测是,在您离开using块之后,NetworkStream将被释放,因为它超出了范围。您可以尝试在使用块结束之前刷新它。或者您的问题出在其他地方了?在使用结束之前尝试刷新memorystream和networkstream,但似乎也没有效果。您需要另一个
ms.Position=0代码>在ms.之后写入
。编辑:实际上第一个ms.Position=0代码>似乎是错误的,因为您正在覆盖刚刚编写的数据。@leppie-Omg,别傻了。我只是想它会将那里的数据向前移动(出于某种原因),但是,你是对的,它只是覆盖了已经写入的内容。这一定是问题所在。@kelton52:我会添加答案,以防万一:)我发现有两件事不对,ns无法解决最后一个块。另外,我不想关闭网络流。我将对其进行修改,并对其进行一次尝试。在外部使用ns进行更新,但没有关闭。没关系,我可能没有提供足够的详细信息或其他信息。我希望消息大小位于流的开头,这是否可行?这似乎会把它抛在数据后面。对不起,再次缺乏细节。这基本上就是我开始使用的代码,但我想重写它,这样我就不必有任何超出messsize的数组。我正在尝试快速完成这项工作,每次数据都超过1mb(用于lan连接)。我希望能够以一种不必将流放入数组的方式操作流,这是最昂贵的调用。@kelton52:使用2个MemoryStream可能是最好的选择,或者,不要使用stream.CopyTo
。我会(再次)更新答案。是的,更新2是我刚想到的,但为什么你说不要使用Stream.CopyTo?@kelton52:因为缺乏明确的文档。有关设置位置的信息,请参见注释。毕竟,在它下面只做Stream.Read
和Stream.Write
。