Получение фрагментированных данных из Socket в один буфер - PullRequest
0 голосов
/ 03 мая 2009

Я пытаюсь написать простой клиент SNPP (Simple Network Paging Protocol), используя сокеты. Кажется, все работает хорошо, за исключением небольшого несоответствия между серверами.

Когда я отправляю команду, мне нужно прочитать ответ, который обычно представляет собой один фрагмент данных. Однако сервер Sprint SNPP отправляет ответы в двух частях. Первый фрагмент данных является первой цифрой кода состояния. Второй кусок - это остаток. Например, когда я пытаюсь получить ответ «220 Gateway ready», он приходит так:

2

Я должен отправить еще одну пустую команду, чтобы получить остальные:

20 Gateway ready

На данный момент я использую:

byte[] buffer = new byte[256];
socket.Receive(buffer);

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

Ответы [ 5 ]

3 голосов
/ 03 мая 2009

Для фрагментированных ответов я бы порекомендовал вам прочитать такие данные:

using (var resultStream = new MemoryStream())
{
    const int CHUNK_SIZE = 2 * 1024; // 2KB, could be anything that fits your needs
    byte[] buffer = new byte[CHUNK_SIZE];
    int bytesReceived;
    while ((bytesReceived = socket.Receive(buffer, buffer.Length, SocketFlags.None)) > 0)
    {
        byte[] actual = new byte[bytesReceived];
        Buffer.BlockCopy(buffer, 0, actual, 0, bytesReceived);
        resultStream.Write(actual, 0, actual.Length);
    }

    // Do something with the resultStream, like resultStream.ToArray() ...
}
1 голос
/ 03 мая 2009

Попробуйте проверить свойство Socket.Available, чтобы определить, нужно ли вам снова вызывать метод Receive.

0 голосов
/ 21 августа 2013

All

Когда веб-сервер отправляет данные в виде «чанков», он предшествует каждому чанку своей длиной (в виде строки, указывающей шестнадцатеричное значение).

размер куска [; кусок расширение] Кусок-данных

Например: разделить на 15 байтов:

F; 123456789ABCDEF

Самая большая проблема с получением HTTP-данных из Socket - это определение объема данных для чтения: если вы получили все доступные данные и снова вызвали метод Recieve, то метод Recieve будет блокироваться, пока удаленный сокет не отправит больше данных что для соединения HTTP / 1.0 никогда не произойдет.

Вам нужно реализовать ридер, который обернут вокруг сокета; он должен получать данные в буфер и предоставлять метод «ReadLine», который читает содержимое буфера до тех пор, пока не будет прочитано 13, а затем 10 (CRLF)

0 голосов
/ 03 мая 2009

Socket.Receive возвращает целое число, которое является числом полученных байтов. Вы можете проверить, равен ли это 1, и снова позвонить Receive.

byte[] buffer = new byte[256];
int len = socket.Receive(buffer);

if (len == 1)
  socket.Receive(buffer, 1, buffer.Length - 1, SocketFlags.None);
0 голосов
/ 03 мая 2009

Мне кажется, я понимаю ваш вопрос. Эта перегрузка Socket.Receive позволяет передавать целое число, чтобы указать позицию смещения, чтобы начать размещение данных. Если вы получили 1 байт, при первом вызове, как в вашем примере, вы можете вызвать эту перегрузку со смещением 1 и использовать тот же буфер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...