大規模なバイト配列を使用した場合のソケット経由で大きなシリアライズされたオブジェクトを送信すると、バイト配列を成長しようとしたときにのみ失敗しますが、OKです
-
22-09-2019 - |
質問
私は自分のソケットを介してデータを受信しながら、バイト配列を成長しようとしているコードを持っています。これはアウトerroringされます。
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:入力ストリームが有効なバイナリフォーマットではありません。 (バイト単位)を出発内容は次のとおり68-61-73-43-68-61-6E-67-65-73-3D-22-69-6E-73-65-72 ...
しかし、私はちょうど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;
}
}
これは本当に私を殺しています。その動作していない理由を私は知りません。私はかなり確信して、これは間違ったことをやっていないよので、私は、あまりにもここに提案からコンバイン引き上げてきた?
私は、誰かが私が間違っているつもり場所を指し示すことができると思います。
解決
それ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ネットなどの代替エンコーダを、考えるかもしれません。これは巨大なオブジェクトの問題を解決することがあります。
他のヒント
私はC#のネットワーキングと本当に慣れていないんだけど、あなたはCombine()
を呼び出すたびにバッファしたバイト数を無視する完全な1024のバイトを追加していないソケットを読み取りますか?おそらくsecond
からコピーするバイト数を言ってその機能に少なくとも一つの追加のパラメータを必要とします。