「int msglength = bitconverter.toint32(gzbuffer、0);」の範囲外のインデックス;」
-
27-09-2019 - |
質問
私は現在、C#XNAで作成されたいくつかのゲームに取り組んでいます。ネット(Bout 96kb)を介して膨大なデータを送信する必要があるため、インターネットで見つけたString Compressor/Decompressorコードを使用しています。コードは次のようになります:
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);
}
}
次のように機能します。 -サーバーは、クライアントに送信した後、文字列コンプレッサーを使用して文字列を圧縮します。 - クライアントは圧縮された文字列を受信し、それを解凍して使用可能になります。
奇妙な部分は、ゲームを単独でテストしているときにコードが機能することです。つまり、同じマシンでサーバーとクライアントを実行します。また、友人がサーバーをホストし、接続している友人と一緒にテストしているときにも機能します。だが 私がサーバーをホストしていて、彼が接続しているとき、それは私の友人のために働いていません。彼が私のサーバーに接続すると、彼は「int msglength = bitconverter.toint32(gzbuffer、0);」で「範囲外」を受け取ります。時々彼は幸運で入りますが、ほとんどが失敗し、そのエラーを返します。サーバーが文字列全体を送信していないということですか?ネットワーク送信にlidgren gen3を使用しており、圧縮された文字列はnetmsg.write(compressedstring)として送信されます。
何か案は :) ?ありがとう!
解決
あなたは複数の場所で同じ誤った仮定をしています:それ Stream.Read
一度に要求したすべてのデータを返します。返品値を無視しています。それをしないでください...確かにそれは大丈夫であるべきです MemoryStream
s、十分なデータがあると仮定すると、 MemoryStream.ToArray
バイト配列に変換する方法。
今、あなたはクライアントが文字列をどのように受信しているかを示していません - どこから入手しているのですか?
サーバーが送信する文字列と、クライアントが受信する文字列を記録する必要があります。これが絶対的な最初のステップなので、データが実際に保存されているかどうかを確認できます。
クライアントが空の文字列を解凍しようとしているのではないかと思う - すなわち Convert.FromBase64
空のバイト配列を返していますが、受信されている文字列がわかるまで、進歩を遂げるのは難しいです。