2009-05-03 2 views
0

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

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

2 

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

20 Gateway ready 

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

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

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

ответ

3

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

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() ... 
} 
+0

Мне нравится это решение, потому что оно обрабатывает куски всех размеров. Однако после получения первого ответа приложение перестает отвечать, пока не появятся новые данные. Отладчик показывает, что он зависает при условии while. –

1

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

0

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

0

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); 
-1

Все,

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

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

например: в порции 15 байт:

F; 123456789ABCDEF

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

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

Смежные вопросы