Получить все байты из networkstream.Читать в однобайтовый массив

#arrays #vb.net #tcpclient #networkstream

#массивы #vb.net #tcpclient #networkstream

Вопрос:

У меня есть TCP-сервер (камера линейного сканирования), который на основе спецификаций отправляет мне данные изображения. Данные изображения представлены в виде 1D байтового массива. Количество байтов, отправленных камерой, известно, но оно может варьироваться в зависимости от спецификации, поэтому иногда это будет очень большое число, а иногда и маленькое. Я использую Networkstream.Прочитайте, чтобы получить байты и попытаться сохранить их в массив.

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

Это код, который я использую сейчас. Я все еще новичок в VB. Я попытался сохранить данные в массивы, а затем добавить их, но почему-то VB не предоставляет такой функциональности.

         Dim imageData(numberOfColumns * numberOfLines - 1) As Byte
        Dim bytesReceived = 
        Dim bytesReceivedTotal = 0
        Dim bytesToRcv = numberOfColumns * numberOfLines
        Dim imageFragment() As Byte
        Dim rcvbytes(8092) As Byte 'tried socket.receivebuffersize too
        Dim readCount = 0

        Do
            bytesReceived = clientStream.Read(rcvbytes, 0, rcvbytes.Length) 
            bytesReceivedTotal  = bytesReceived
            rcvbytes.CopyTo(imageData, (bytesReceivedTotal - bytesReceived))
        Loop Until bytesReceivedTotal = bytesToRcv
  

Проблема с этим кодом заключается в том, что длина rcvbytes не изменяется при последнем чтении. Есть ли способ сохранить все данные из потока в однобайтовом массиве? размер байтов, отправленных сервером, определяется следующим образом: (numberOfLines * numberOfColumns)

ОБНОВЛЕНИЕ # 2: РАБОЧИЙ КОД

             Do
            Dim bytesWanted As Integer = bytesReceivedTotal   8092
            Dim bytesToRead As Integer = If(bytesWanted > imageData.Length, imageData.Length - bytesReceivedTotal, 8092)


            bytesReceived = clientStream.Read(imageData, bytesReceivedTotal, bytesToRead)
            bytesReceivedTotal  = bytesReceived
        Loop Until bytesReceivedTotal = bytesToRcv
  

Ответ №1:

Поскольку TCP является потоковым протоколом, единственный способ надежно поместить все ожидаемые данные (целое «сообщение») в один массив — это продолжать вызывать NetworkStream.Read() , пока вы не прочитаете достаточное количество байтов.

Я попытался сохранить данные в массивы, а затем добавить их, но почему-то VB не предоставляет такой функциональности.

Это неверно. Существует несколько способов объединения фрагментов данных. Вы могли бы, например, использовать List(Of T) .

Однако в вашем случае ответ на самом деле прямо у вас под носом. Если вы посмотрите на NetworkStream.Read() документацию, вы можете увидеть, что второй параметр (вызывается offset ) указывает «Местоположение, в buffer котором начинается хранение данных» — где buffer находится массив байтов, который вы указываете в качестве первого параметра.

Если вы зададите offset параметру количество уже прочитанных байтов, он добавит новые байты после уже полученных в массив. Также имейте в виду, что вы не хотите читать слишком много, если приближаетесь к концу массива.

 Dim bytesWanted As Integer = bytesReceivedTotal   8092
Dim bytesToRead As Integer = If(bytesWanted > imageData.Length, imageData.Length - bytesReceivedTotal, 8092)

clientStream.Read(imageData, bytesReceivedTotal, bytesToRead)
  

Комментарии:

1. Я сделал это, используя другой метод несколько минут назад, но ваш код полностью имеет смысл. Я использовал поток памяти для записи данных из буфера, и это работает. Какой из них более предпочтителен? PS: Кажется, я не могу правильно вставить код. Первый раз с использованием stackoverflow

2. @ShamsRKhan: Мой код потребляет меньше памяти, чем ваш, поскольку при использовании a MemoryStream оба сохраняют данные, которые вы передаете, в виде новой копии в памяти, но также создают совершенно новый массив при вызове MemoryStream.ToArray() , в то время как мой записывает непосредственно в основной массив (таким образом, это также немного быстрее). — Также, пожалуйста, не помечайте его как ответ, прежде чем вы его протестировали. Лучше сначала проверить, работает это или нет.

3. @ShamsRKhan : Копирование кода иногда может быть немного сложным… Просто попробуйте выделить все это, перетащив выделение за пределы блока кода.

4. @ShamsRKhan : Отлично! Я рад, что смог помочь! Удачи с вашим проектом! 🙂