Bonjour J'essaie d'envoyer et de recevoir des données entre l'application client/serveur.Liste de désérialisation <T> sur le problème de réseau
Classe
[Serializable]
public class ScanSessie
{
public string UserId { get; set; }
public int TotalScanned { get; set; }
public string Status { get; set; }
public string DeviceId { get; set; }
}
sérialiseur et désérialiseur méthodes d'extension:
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;
}
}
L'exemple des données que je suis en train d'envoyer et de désérialiser est:
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 });
Envoi avec le code suivant :
NetworkStream broadcastStream = statusSocket.GetStream();
Byte[] broadcastBytes = SerializerDeserializerExtensions.Serializer(scannerCl);
broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
broadcastStream.Flush();
Réception du code de flux. ignore la boucle n.DataAvailable. J'envoie à des fins de test de très petits paquets bien en dessous du tampon qui est transféré en une partie.
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;
}
}
Le code de réception déclenchera un événement avec les données comme octet [] défini comme message. Sur mon événement de traitement j'essaie de désérialiser avec:
private void Sc_NewDataReceived(byte[] scanner)
{
try
{
var result = scanner.Deserializer<List<ScanSessie>>();
}
catch(Exception ex)
{
Debug.WriteLine(ex.InnerException);
}
}
Sur l'étape de deserialize il lancera une exception (exception levée: « System.Runtime.Serialization.SerializationException » dans mscorlib.dll) InnerException est nulle .
Lorsque j'utilise les méthodes d'extension sans les envoyer sur réseau avec quelques exemples de données, la désérialisation fonctionne parfaitement.
J'ai également essayé de jouer avec les tailles de mémoire tampon de réception. Cela ne semble pas aider aussi. L'exemple de taille de données est inférieur à 1024 * 8.
Si la longueur des données d'envoi est de 600 octets par exemple. Le tampon final de réception doit-il également avoir la même taille? Normalement cela devrait être un problème car il se lit en morceaux.
Après 2 jours, j'abandonne. Toute aide serait appréciée. J'ai essayé de rendre la question informative en plaçant les extraits de code de fonctionnement.
Si la taille de votre message est inférieure à la taille de la mémoire tampon (1024 * 8), le reste de votre mémoire tampon est rempli de zéros, ce qui, bien sûr, empêche la désérialisation correcte. Sans oublier que chaque lecture écrase une partie de la mémoire tampon (dans la boucle 'while DataAvailable'). – Evk
L'utilisation de NetworkStream.Length n'est pas prise en charge. Vous devez donc définir une taille de mémoire tampon fixe. Grand ou petit. Pour le tester j'ai vérifié la taille de mes données d'échantillon il était 606 octets. J'ai ajusté le tampon de réception également à 606 octets la même exception se produit. La boucle while l'écrase en effet. C'est un exemple de code. Les données d'envoi sont bien en dessous de la taille de la mémoire tampon, donc elles ne seront pas bouclées :) – Shift
Au lieu de sérialiser via un 'MemoryStream', vous pourriez fournir' '' '' 'NetworkStream'' au '' BinaryFormatter '' directement. Mais si vous voulez traiter les données manuellement, gardez à l'esprit que les opérations 'Read' renvoient le nombre d'octets réellement lus et peuvent recevoir les données en morceaux plus petits que les données envoyées. La réception de 0 octet indique que l'autre côté a fermé son canal d'envoi. –