2010-06-15 6 views
0

Je travaille actuellement sur un jeu fait en C# XNA. Depuis que j'ai besoin d'envoyer une énorme quantité de données sur le net (environ 96kb), j'utilise du code compresseur/décompresseur, que j'ai trouvé sur internet. Le code ressemble à ceci:Indice hors plage à "int msgLength = BitConverter.ToInt32 (gzBuffer, 0);"

 public static string Compress(string text) 
    { 
     byte[] buffer = Encoding.UTF8.GetBytes(text); 
     MemoryStream ms = new MemoryStream(); 
     using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true)) 
     { 
      zip.Write(buffer, 0, buffer.Length); 
     } 

     ms.Position = 0; 
     MemoryStream outStream = new MemoryStream(); 

     byte[] compressed = new byte[ms.Length]; 
     ms.Read(compressed, 0, compressed.Length); 

     byte[] gzBuffer = new byte[compressed.Length + 4]; 
     System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length); 
     System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4); 

     return Convert.ToBase64String(gzBuffer); 
    } 

    public static string Decompress(string compressedText) 
    { 
     byte[] gzBuffer = Convert.FromBase64String(compressedText); 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      int msgLength = BitConverter.ToInt32(gzBuffer, 0); 
      ms.Write(gzBuffer, 4, gzBuffer.Length - 4); 

      byte[] buffer = new byte[msgLength]; 

      ms.Position = 0; 
      using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress)) 
      { 
       zip.Read(buffer, 0, buffer.Length); 
      } 

      return Encoding.UTF8.GetString(buffer); 
     } 
    } 

Il fonctionne comme ceci: - Server compresse la chaîne en utilisant le compresseur de chaîne, où après l'avoir envoyé au client. - Le client reçoit la chaîne compressée et la décompresse pour qu'elle soit utilisable.

Maintenant, la partie bizarre est que le code fonctionne lorsque je teste le jeu seul, ce qui signifie que je lance le serveur et le client sur la même machine. Cela fonctionne également lorsque je suis en train de tester avec mon ami, où il héberge le serveur, et je me connecte. Mais il ne fonctionne pas pour mon ami quand j'héberge le serveur et il se connecte. Lorsqu'il se connecte à mon serveur, il reçoit "Index hors limites" à "int msgLength = BitConverter.ToInt32 (gzBuffer, 0);". Parfois il a de la chance et entre, mais la plupart du temps il échoue et renvoie cette erreur. Peut-être que le serveur n'obtient pas toute la chaîne envoyée? J'utilise Lidgren gen3 pour l'envoi réseau, et la chaîne compressée est envoyée en tant que netMsg.Write (compressedstring);

Des idées :)? Merci!

+0

Collez un Debug.Assert (gzBuffer.Length> = 4); sur la ligne avant d'appeler BitConverter.ToInt32() et vous verrez le problème. Votre gzBuffer ne contient même pas les 4 octets pour lire Int32. –

Répondre

2

Vous faites la même supposition incorrecte à plusieurs endroits: Stream.Read retournera toutes les données que vous avez demandées en une fois. Vous ignorez la valeur de retour. Ne faites pas cela ... il est vrai que cela devrait convenir à MemoryStream s, en supposant qu'il y ait suffisamment de données. En outre, vous pouvez utiliser la méthode MemoryStream.ToArray pour convertir un tableau d'octets.

Maintenant, vous n'avez pas montré comment le client reçoit la chaîne - d'où l'obtenez-vous?

Vous devez enregistrer la chaîne envoyée par le serveur et la chaîne que le client reçoit. C'est la première étape absolue, de sorte que vous pouvez voir si les données ont été préservées.

Je suppose que le client essaie de décompresser une chaîne vide - c'est-à-dire que Convert.FromBase64 renvoie un tableau d'octets vide - mais jusqu'à ce que vous connaissiez la chaîne reçue, il est difficile de progresser.

+0

Salut Jon Skeet, J'ai essayé vos conseils de journalisation de la chaîne qui est envoyée. Il s'avère que le client n'a rien reçu, donc je suppose que je dois travailler avec l'envoi. Merci pour votre aide :) – Mark

Questions connexes