#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 : Отлично! Я рад, что смог помочь! Удачи с вашим проектом! 🙂