Индекс вне диапазона: «int msgLength = BitConverter.ToInt32 (gzBuffer, 0);» - PullRequest
0 голосов
/ 15 июня 2010

В настоящее время я работаю над игрой, созданной на C # XNA.Так как мне нужно отправить огромную порцию данных по сети (около 96 КБ), я использую код сжатия / распаковки строк, который я нашел в Интернете.Код выглядит так:

        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 (сжатая строка);

Есть идеи :)?Спасибо!

1 Ответ

2 голосов
/ 15 июня 2010

Вы делаете одно и то же неверное предположение в нескольких местах: Stream.Read вернет все запрошенные вами данные за один раз.Вы игнорируете возвращаемое значение.Не делайте этого ... по общему признанию, это должно быть хорошо для MemoryStream с, при условии, что данных достаточно. Кроме того, вы можете использовать метод MemoryStream.ToArray для преобразования в байтовый массив.

Теперь выне показали, как клиент получает строку - откуда вы ее получаете?

Вы должны зарегистрировать строку, которую отправляет сервер, и строку, которую получает клиент.Это абсолютный первый шаг, поэтому вы можете увидеть, действительно ли данные были сохранены.

Я подозреваю, что клиент пытается распаковать пустую строку - то есть, что Convert.FromBase64 возвращает пустой байтовый массив - нопока вы не узнаете полученную строку, трудно добиться какого-либо прогресса.

...