Клиент читает из потока нули

356
14 мая 2017, 21:38

Если сообщение больше размера буфера, то на клиент часть данных приходит как нули.

Самым первым уходит общая длина. Потом кусками само сообщение. Вот так я его отправляю данные:

            var bytesLen = BitConverter.GetBytes(buffer.Length);
            await _stream.WriteAsync(bytesLen, 0, bytesLen.Length);
            if (message.Command == 7 || message.Command == 8)
                Program.CommandLogger.Info($"{BitConverter.ToString(bytesLen)} ->");
            var countSegment = Math.Ceiling(buffer.Length / (double)BufferSize);
            for (int index = 0; index < countSegment; index++)
            {
                var bytes = buffer.Skip(index * BufferSize).Take(BufferSize).ToArray();
                await _stream.WriteAsync(bytes, 0, bytes.Length);
                if (message.Command == 7 || message.Command == 8)
                    Program.CommandLogger.Info($"<- {BitConverter.ToString(bytes.Take(10).ToArray())}");
            }

Вот данные (первые 10 байт из каждого сегмента) которые сервер должен отправить:

5E-8B-00-00 -> - 
<- 02-07-7B-22-48-6F-6D-65-49-64 - 
<- 56-61-6C-75-65-22-3A-37-2E-35 - 
<- 7B-22-4E-61-6D-65-22-3A-22-31 - 
<- 6D-65-22-3A-22-32-3A-33-22-2C - 
<- 77-6F-6E-22-2C-22-56-61-6C-75 - 

Вот что читает клиент.

5E-8B-00-00
<- 77-6F-6E-22-2C-22-56-61-6C-75
<- 00-00-00-00-00-00-00-00-00-00
<- 00-00-00-00-00-00-00-00-00-00
<- 00-00-00-00-00-00-00-00-00-00
<- 00-00-00-00-00-00-00-00-00-00

Дополнил кодом чтения.

 private async Task<byte[]> ReceiveTask(int byteCount)
        {
            var buffer = new byte[byteCount];
            var pos = 0;
            while (pos < byteCount)
            {
                var count = await _stream.ReadAsync(buffer, 0, buffer.Length);
                if (count == 0)
                    throw new EndOfStreamException();
                pos += count;
            }
            return buffer;
        }
        public async void Receive()
        {
            try
            {
                while (true)
                {
                    var packetLenBytes = await ReceiveTask(4);
                    var packetlen = BitConverter.ToInt32(packetLenBytes, 0);
                    var data = await ReceiveTask(packetlen);
                    var countSegment = Math.Ceiling(data.Length / (double)BufferSize);
                    Console.WriteLine(BitConverter.ToString(packetLenBytes));
                    for (int index = 0; index < countSegment; index++)
                    {
                        var bytes = data.Skip(index * BufferSize).Take(BufferSize).ToArray();
                        Console.WriteLine(@"<- " + BitConverter.ToString(bytes.Take(10).ToArray()));
                    }
                    RaiseEventMessegaReceive(data);
                }
            }
            catch (OutOfMemoryException exception)
            {
                Console.WriteLine(exception);
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
                Dispose();
            }
        }
Answer 1

Попробуйте вместо

await _stream.ReadAsync(buffer, 0, buffer.Length);

такое:

await _stream.ReadAsync(buffer, pos, buffer.Length - pos);
Answer 2

Если сообщение больше размера буфера

Какого буфера?

Вот так я его отправляю данные:

А читаете как?

Сервер посылает на клиент нули

Откуда известно, что именно сервер? Вы проверяли с помощью сниффера, например, Wireshark?

Скорее всего, проблема как раз в чтении - вы не учитываете того, что при чтении может вернуться меньше байт, чем было запрошено, обычно такое происходит, когда отправляемый буфер занимает больше 1 сегмента. Для этого read() возвращает число байт, сколько реально считано. Если считано недостаточно, нужно "дочитывать". Вот так это выглядит в синхронном варианте:

       /* Reading payload */
        var bufBody = new byte[length];
        int tryN = 0;
        int totalReaden = 0;
        while (true)
        {
            try
            {
                tryN++;
                var readenBody =
                    client.GetStream().Read(
                    bufBody, totalReaden, bufBody.Length - totalReaden);
                if (readenBody == 0)
                {
                    throw new Exception(cip + "Read 0 bytes"); // это разрыв соединения
                }
                totalReaden += readenBody;
                if (totalReaden == bufBody.Length)
                {
                    break;
                }
                log(cip + "WARNING: " + tryN + " read not yet readen");
            }
            catch (Exception ex)
            {
                log(cip + "ERROR: Cannot read body at" + tryN + ". Client rejected"); // это тоже разрыв, либо "явный" либо "неявный" (обрыв кабеля на длительное время и истек тайм-аут)
                log(ex);
                client.Client.Disconnect(true);
                return; 
            }
        }
READ ALSO
Файловый менеджер C# Ошибка Перемещение файла

Файловый менеджер C# Ошибка Перемещение файла

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

353
Файловые ассоциации в Xamarin Android

Файловые ассоциации в Xamarin Android

Пытаюсь разобраться с подключением открытия для своего расширения файлаКак это заставить работать правильно: MainActivity

344
SignalR асинхронное подключение + Unity3D

SignalR асинхронное подключение + Unity3D

Пытаюсь разобраться с тем, как выполнить асинхронное подключение к хабу в SignalRИзначально использовал такой код:

387
Чтение Excel файла взять данные из колонки

Чтение Excel файла взять данные из колонки

Возникла проблема с чтением excel файла, мне нужно взять данные из колонки с определенным именем

304