こんにちは、私はクライアント/サーバーアプリケーション間でいくつかのデータを送受信しようとしています。デシリアライズリスト<T>ネットワークストリームでの問題
クラス
[Serializable]
public class ScanSessie
{
public string UserId { get; set; }
public int TotalScanned { get; set; }
public string Status { get; set; }
public string DeviceId { get; set; }
}
シリアライザとデシリアライザ拡張メソッド:私はそれを送信し、デシリアライズしようとしています
public static class SerializerDeserializerExtensions
{
public static byte[] Serializer(this object _object)
{
byte[] bytes;
using (var _MemoryStream = new MemoryStream())
{
IFormatter _BinaryFormatter = new BinaryFormatter();
_BinaryFormatter.Serialize(_MemoryStream, _object);
bytes = _MemoryStream.ToArray();
}
return bytes;
}
public static T Deserializer<T>(this byte[] _byteArray)
{
T ReturnValue;
using (var _MemoryStream = new MemoryStream(_byteArray))
{
IFormatter _BinaryFormatter = new BinaryFormatter();
ReturnValue = (T)_BinaryFormatter.Deserialize(_MemoryStream);
}
return ReturnValue;
}
}
例のデータは次のとおりです。
次のコードで送信List<ScanSessie> scannerCl = new List<ScanSessie>();
scannerCl.Add(new ScanSessie { DeviceId = "0x00456321", UserId = "123456", Status = "scannen ...", TotalScanned = 0 });
scannerCl.Add(new ScanSessie { DeviceId = "0x00456321", UserId = "123456", Status = "scannen ...", TotalScanned = 0 });
scannerCl.Add(new ScanSessie { DeviceId = "0x00456321", UserId = "123456", Status = "scannen ...", TotalScanned = 0 });
scannerCl.Add(new ScanSessie { DeviceId = "0x00456321", UserId = "123456", Status = "scannen ...", TotalScanned = 0 });
scannerCl.Add(new ScanSessie { DeviceId = "0x00456321", UserId = "123456", Status = "scannen ...", TotalScanned = 0 });
scannerCl.Add(new ScanSessie { DeviceId = "0x00456321", UserId = "123456", Status = "scannen ...", TotalScanned = 0 });
:
NetworkStream broadcastStream = statusSocket.GetStream();
Byte[] broadcastBytes = SerializerDeserializerExtensions.Serializer(scannerCl);
broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
broadcastStream.Flush();
ストリームコードを受信しています。 n.DataAvailableループを無視します。私はテスト目的のために、ある部分で転送されるバッファの下に非常に小さなパケットの方法で送信しています。
using (TcpClient client = new TcpClient())
{
await client.ConnectAsync("10.184.32.39", 8888);
ConnectionEstabilished?.Invoke();
byte[] message = new byte[1024 * 8];
int bytesRead;
using (NetworkStream n = client.GetStream())
{
while (true)
{
bytesRead = 0;
try
{
if(n.CanRead)
{
do
{
bytesRead = await n.ReadAsync(message, 0, message.Length);
}
while (n.DataAvailable);
}
//bytesRead = await n.ReadAsync(message, 0, 4096);
//bytesRead = await n.ReadAsync(message, 0, message.Length);
}
catch (Exception ex)
{
// some error hapens here catch it
Debug.WriteLine("DashboardClientConnect " + ex.Message + "\n" + ex.InnerException);
break;
}
}
受信コードは、メッセージとして定義されたbyte []のデータを持つイベントを発生させます。それは例外がスローされますデシリアライズステップに
private void Sc_NewDataReceived(byte[] scanner)
{
try
{
var result = scanner.Deserializer<List<ScanSessie>>();
}
catch(Exception ex)
{
Debug.WriteLine(ex.InnerException);
}
}
(例外がスローさ:がmscorlib.dllで「System.Runtime.Serialization.SerializationException」)私はそれをデシリアライズしようとする私の処理イベントで のInnerExceptionがnull 。
ネットワークを介していくつかのサンプルデータを送信せずに拡張メソッドを使用すると、デシリアライズは完全に機能します。
また、私は受信バッファサイズで遊んでみました。それはまた助けているようではありません。データサイズの例は1024 * 8以下です。
たとえば、送信データ長が600バイトの場合。受信側のバッファも同じサイズでなければなりませんか?通常、チャンクを読み込むので問題になるはずです。
2日後、私はあきらめます。どんな助けもありがとう。私は機能的なコードスニペットを配置して質問を有益にしようとしました。
メッセージサイズがバッファサイズ(1024 * 8)より小さい場合は、バッファの残りの部分がゼロで埋められます。これにより、正しく逆シリアル化されません。言うまでもなく、各読み取りはバッファの一部を上書きします( 'while DataAvailable'ループ内)。 – Evk
NetworkStream.Lengthの使用はサポートされていないため、固定バッファサイズを定義する必要があります。大なり小なり。 これをテストするために、サンプルデータのサイズを確認しました。これは606バイトでした。受信バッファも同じ例外が発生する606バイトに調整しました。 whileループが実際に上書きしています。サンプルコードです。送信データはバッファサイズよりも小さいので、ループしません:) – Shift
'MemoryStream'を介してシリアル化するのではなく、' NetworkStream'を 'BinaryFormatter'に直接提供することができます。しかし、手動でデータを処理したい場合は、 'Read'演算が実際に読み取られたバイト数を返し、送られたデータよりも小さなチャンクでデータを受け取ることに注意してください。 0バイトを受信すると、相手側が送信チャネルを閉じたことを示します。 –