3

ソケット経由でデータを受信しながら、バイト配列を拡張しようとしているコードがあります。これはエラーになっています。

    public bool ReceiveObject2(ref Object objRec, ref string sErrMsg)
    {
        try
        {
            byte[] buffer = new byte[1024];
            byte[] byArrAll = new byte[0];
            bool bAllBytesRead = false;

            int iRecLoop = 0;

            // grow the byte array to match the size of the object, so we can put whatever we 
            // like through the socket as long as the object serialises and is binary formatted 
            while (!bAllBytesRead)
            {
                if (m_socClient.Receive(buffer) > 0)
                {
                    byArrAll = Combine(byArrAll, buffer);
                    iRecLoop++;
                }
                else
                {
                    m_socClient.Close();
                    bAllBytesRead = true;
                }
            }

            MemoryStream ms = new MemoryStream(buffer);
            BinaryFormatter bf1 = new BinaryFormatter();
            ms.Position = 0;
            Object obj = bf1.Deserialize(ms);
            objRec = obj;

            return true;
        }
        catch (System.Runtime.Serialization.SerializationException se)
        {
            objRec = null;
            sErrMsg += "SocketClient.ReceiveObject " + "Source " + se.Source + "Error : " + se.Message;
            return false;
        }
        catch (Exception e)
        {
            objRec = null;
            sErrMsg += "SocketClient.ReceiveObject " + "Source " + e.Source + "Error : " + e.Message;
            return false;
        }
    }

    private byte[] Combine(byte[] first, byte[] second)
    {
        byte[] ret = new byte[first.Length + second.Length];
        Buffer.BlockCopy(first, 0, ret, 0, first.Length);
        Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
        return ret;
    }    

エラー: mscorlibError : 入力ストリームが有効なバイナリ形式ではありません。最初の内容 (バイト単位) は次のとおりです。

それでも、MASSIVEバッファサイズをごまかして使用すると問題ありません。

        public bool ReceiveObject(ref Object objRec, ref string sErrMsg)
    {
        try
        {
            byte[] buffer = new byte[5000000];

            m_socClient.Receive(buffer);
            MemoryStream ms = new MemoryStream(buffer);
            BinaryFormatter bf1 = new BinaryFormatter();

            ms.Position = 0;
            Object obj = bf1.Deserialize(ms);
            objRec = obj;

            return true;
        }
        catch (Exception e)
        {
            objRec = null;
            sErrMsg += "SocketClient.ReceiveObject " + "Source " + e.Source + "Error : " + e.Message;
            return false;
        }
    }

これは本当に私を殺しています。なぜ機能しないのかわかりません。ここでも提案から結合を解除したので、これは間違ったことをしていないと確信していますか?

誰かが私が間違っているところを指摘してくれることを願っています

4

2 に答える 2

2

この方法は、特にこれに対処するように設計されているCombine場合、配列を大きくするための非常にコストのかかる方法です。他の回答は正しいです。読み取ったバイト数を確認する必要があります。MemoryStream

using(MemoryStream ms = new MemoryStream()) {
    int bytesRead;
    while((bytesRead = m_socClient.Receive(buffer)) > 0) {
        ms.Write(buffer, 0, bytesRead);
    }
    // access ms.ToArray() or ms.GetBuffer() as desired, or
    // set Position to 0 and read
}

もちろん、ストリームから直接読み取ることもできます (リーダーに渡します)。

また、シリアル化が大きすぎる場合は、protobuf-net などの代替エンコーダーを検討することもできます (ただし、これによりコードが少し変更されます)。これにより、巨大なオブジェクトの問題が解決される場合があります。

于 2010-01-25T19:30:09.913 に答える
1

私は C# ネットワーキングにあまり詳しくありませんが、呼び出しのたびに 1024 バイトをバッファに追加Combine()し、ソケットから読み取ったバイト数を無視していませんか? おそらく、その関数には、コピー元のバイト数を示す追加のパラメーターが少なくとも 1 つ必要ですsecond

于 2010-01-25T18:25:21.700 に答える