Индекс вне диапазона на "int msglength = bitconverter.toint32 (gzbuffer, 0);"
-
27-09-2019 - |
Вопрос
В настоящее время я работаю над какой-то игрой, сделанной в C # XNA. Поскольку мне нужно отправить огромную кусок данных по сети (BOT 96KB), я использую несколько строковых компрессоров / декомпрессорного кода, который я нашел в Интернете. Код выглядит так:
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, предполагая, что достаточно DAABADDITYALL, вы можете использовать MemoryStream.ToArray
Способ преобразования в байтовый массив.
Теперь вы не показали, как клиент получает строку - откуда вы получаете?
Вы должны регистрировать строку, которую сервер отправляет, и строка, которую получает клиент. Это абсолютный первый шаг, так что вы можете увидеть, были ли данные на самом деле сохранены.
Я подозреваю, что клиент пытается распаковать пустую строку - то есть это Convert.FromBase64
Возвращает пустую байтовую массив - но пока вы не знаете строку, которая принимается, трудно добиться прогресса.