проблемы с копией потока памяти в сетевой поток - PullRequest
1 голос
/ 29 ноября 2011

У меня проблема с этим кодом.

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) просто не работает?

По сути, я хочу сериализовать класс в сетевой поток с предшествующим ему размером сериализованных данных.Если у кого-то есть лучший способ сделать это, дайте мне знать!

Ответы [ 3 ]

2 голосов
/ 29 ноября 2011

Вы сбрасываете позицию потока в неправильное время.

В вашем случае вы пишете 'length' в начало потока.

Должно работать следующее:

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

Обновление:

Для записи 'length' в начало используйте временный поток / байт [].

Пример:

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 голосов
/ 29 ноября 2011

Я не вижу реальной проблемы, но я вижу здесь небольшую проблему с рефакторингом.

Попробуйте использовать

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 голосов
/ 29 ноября 2011

Возможно, вам нужно перемотать поток памяти в начало перед вызовом CopyTo (используйте ms.Seek (0, SeekOrigin.Start))

...