2011-11-29 82 views
1

我在這裏遇到此代碼的問題。內存流copyto網絡流問題

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(); 
} 

我找不出這裏發生了什麼,或者爲什麼它不工作。它看起來像eather它不會複製,或者它關閉網絡流,或什麼。

對不起,我試過調試它,但如果任何人都可以在這裏看到任何明顯的問題,我將不勝感激。

順便說一句,該類序列化很好,並且MemoryStream包含數據,但由於某種原因,做一個ms.CopyTo(ns)似乎並不工作?

本質上,我想要做的就是將類序列化到網絡流,並在其之前的序列化數據的大小。如果有人有更好的方法來做到這一點,讓我知道!

+1

我的猜測是,在你離開使用塊之後,NetworkStream被處置,因爲它超出了範圍。您可以嘗試在使用塊結束之前將其刷新。或者你的問題在別的地方? –

+0

嘗試在使用結束之前刷新內存流和網絡流,但似乎也沒有這樣做。 –

+0

'ms.Write'後面需要另一個'ms.Position = 0;'。編輯:實際上,首先'ms.Position = 0;'似乎是錯誤的,因爲你正在覆蓋你剛剛寫的數據。 – leppie

回答

2

您正在重設錯誤時間的流位置。

在你的情況,你寫'流'的開始'長度'。

以下應該工作:

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); 
} 
+0

我希望消息大小在流的開頭,這是否正常工作?看起來這會把數據拋在後面。 –

+0

@ kelton52:更新:) – leppie

+0

對不起,再次缺乏細節。這基本上是我開始使用的代碼,但我想重寫它,所以我不必在messsize之外有任何數組。我試圖做得非常快,每次數據超過1mb(用於LAN連接)。我希望能夠以一種能夠讓我不必將數據流放入數組中的方式操縱數據流,這是最昂貴的通話方式。 –

0

也許你需要調用CopyTo從(使用ms.Seek(0,SeekOrigin.Start))

+0

我其實只是試過,似乎沒有關係。 –

0

我沒有看到一個真正的問題之前倒帶內存流的開始,但我看到豆蔻重構問題這裏。

使用

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(); 
    } 
} 

在這之後,你應該能夠找到你的問題。

+0

我發現兩件事情是錯誤的,ns不會解析爲finally塊。另外,我不想關閉網絡流。我會修改它,然後給它一個鏡頭。 –

+0

在ns外面更新並且沒有關閉。 – oberfreak

+0

另外,爲什麼在MemoryStream之前刷新NetworkStream? –