Índice fora do alcance em “int msglength = bitconverter.toint32 (gzbuffer, 0);”
-
27-09-2019 - |
Pergunta
Atualmente, estou trabalhando em algum jogo feito em C# XNA. Como preciso enviar uma grande parte dos dados sobre a rede (luta de 96kb), estou usando algum código de compressor/descompressor de string, que encontrei na Internet. O código se parece com o seguinte:
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);
}
}
Funciona assim: - O servidor comprime a string usando o String Compressor, onde depois de enviá -lo para o cliente. - O cliente recebe a sequência compactada e a descompacte para que seja utilizável.
Agora, a parte estranha é que o código funciona quando estou testando o jogo sozinho, o que significa que eu executo o servidor e o cliente na mesma máquina. Também funciona quando estou testando com meu amigo, onde ele hospeda o servidor, e eu conecto. Mas Não está funcionando para meu amigo quando estou hospedando o servidor e ele se conecta. Quando ele se conecta ao meu servidor, ele recebe "índice fora do alcance" em "int msglength = bitconverter.toint32 (gzbuffer, 0);".Às vezes, ele tem sorte e entra, mas principalmente falha e retorna esse erro. Será que o servidor não está enviando a string inteira? Estou usando o Lidgren Gen3 para envio de rede e a sequência compactada é enviada como netmsg.write (comprimedString);
Alguma ideia :) ? Obrigado!
Solução
Você está fazendo a mesma suposição incorreta em vários lugares: que Stream.Read
retornará todos os dados que você pediu de uma só vez. Você está ignorando o valor de retorno. Não faça isso ... é certo que deveria estar bem para MemoryStream
s, assumindo que há dados suficientes, você pode querer usar o MemoryStream.ToArray
Método para converter em uma matriz de bytes.
Agora, você não mostrou como o cliente está recebendo a string - de onde você está obtendo?
Você deve registrar a string que o servidor envia e a string que o cliente recebe. Esse é o primeiro passo absoluto, para que você possa ver se os dados foram realmente preservados.
Eu suspeito que o cliente esteja tentando descomprimir uma corda vazia - ou seja, isso Convert.FromBase64
está retornando uma matriz de bytes vazia - mas até você conhecer a string que está sendo recebida, é difícil fazer qualquer progresso.