LINUX.ORG.RU

Как найти заголовок в текстовых протоколах?

 , , ,


0

2

Как считывать данные и искать заголовки из текстовых протоколов? Вроде HTTP? Я отправляю запрос в сокет.

Мне приходит ответ

HTTP/1.0 200 OK
Server: nginx/0.6.31
Content-Language: ru
Content-Type: text/html; charset=utf-8
Content-Length: 1234

<данные>

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

Считывать побайтово пока не встречу \r\n\r\n?

Мне кажется, побайтово считывать медленно.


Считывать побайтово пока не встречу \r\n\r\n?

Я бы так и делал. Только читал бы не побайтово, а большими порциями.

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от Reset

Читай неблокирующим read'ом

С чего вы взяли, что ТСу именно неблокирующий надо?

ищи в потоке \r\n\r\n

Ну да, а Content-Length, charset, cookie и т д - это типа совсем не надо парсить, ага. Ладно ещё не нарвётесь на HTTP/0.NN, где двойной пустой строки вообще нет.

vodz ★★★★★
()

принято заводить под это дело отдельный буфер,
куда дописываются полученные байты,
после чего данные сплитятся на \n(\r), и заганяютя в список,
а уже в списке ищутся нужные данные, будь то контент длинна или еще что то
это в простом варианте

anonymous
()

побайтово считывать медленно

И ты, мешок с костями, ещё рассуждаешь о медленности?

По теме: сообщение (запрос) состоит из элементарных сообщений (строка до разделителя), которые могут быть статусом, выражением или данным.

Раз в определении присутствует байт (конец строки), то да - считыать побайтно.

Если бы байт не упоминался, то нижней границей было бы элементарное сообщение.

anonymous
()
Ответ на: комментарий от vodz

С чего вы взяли, что ТСу именно неблокирующий надо?

С того что он не хочет читать по одному байту. С блокирующим только так.

Reset ★★★★★
()
Ответ на: комментарий от Reset

С того что он не хочет читать по одному байту. С блокирующим только так.

ioctl(socket, FIONREAD, &ready_for_read);

vodz ★★★★★
()
Ответ на: комментарий от rumgot

А каким выбрать размер порции? В этом загвоздка

Я беру размер 512 байт, а если весь ответ меньше? У меня read будет висеть и ждать

JANB
() автор топика
Ответ на: комментарий от anonymous

Раз в определении присутствует байт

В определении моем, которое я дал? Я мог и фигню сморозить. мне интересно как люди читают http, необязательно побайтно

JANB
() автор топика
Ответ на: комментарий от RazrFalcon

Какие то монстры в ответе гугла

JANB
() автор топика
Ответ на: комментарий от anonymous

И по сколько считывать? Что делать если ответ меньше чем порция для считывания и сокет блокирующий?

JANB
() автор топика
Ответ на: комментарий от JANB

Это зависит от того, с помощью каких функций/библиотек ты работаешь с сетью. Я могу подсказать, как это делается на c++/Qt или c++/Boost.asio .

rumgot ★★★★★
()
Ответ на: комментарий от JANB

Что делать если ответ меньше чем порция для считывания и сокет блокирующий?

recv() прочитает и вернет количество прочитанных байт. Блокироваться не будет

http://man7.org/linux/man-pages/man2/recv.2.html

These calls return the number of bytes received, or -1 if an error occurred.

Логика немного сложнее, если данных пришло больше буфера. Нужно вычитывать до тех пор пока recv() > 0.

Deleted
()
Ответ на: комментарий от JANB

Ничто не мешает. Это неэффективно. Слишком много сисколов.

Reset ★★★★★
()
Ответ на: комментарий от Deleted
If no messages are available at the socket, the receive calls wait
       for a message to arrive, unless the socket is nonblocking

И с чего это не должен блокироваться блокирующий сокет ?

Reset ★★★★★
()
Ответ на: комментарий от Reset

linux-only хак.

Нет, этот ioctl-код был, когда Linux-а ещё не было. Тогда даже сети не было, использовался для узнавания, сколько можно прочитать чего-либо (то есть в основном из tty).

vodz ★★★★★
()

Используй так длина Content-Length: = 16

char *ptr = strstr ( buf, "Content-Length:" );
ptr += 17;
int length = atoi ( ptr );

u0atgKIRznY5
()
Ответ на: комментарий от Reset

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

Deleted
()

Понятие «протокол» подразумевает как раз свод правил, которых будут придерживаться машины при обмене данными. В твоём случае, конечно, нужно опираться на протокол, а это значит, что получив знание о том по какому протоколу к тебе обратились ты уже принимаешь решение как интерпретировать всё остальное. Представь, что нет никакой универсальной последовательности байт, которую всегда можно интерпретировать как «всё, вот тут конец», всё зависит от протокола и в данном случае конец - это «\r\n\r\n», а также как тут выже сказали, бывают и другие вариации протокола HTTP и уже тебе решать будет ли твой софт его поддерживать.

c3ph
()
Ответ на: комментарий от Reset

Читай неблокирующим read'ом столько сколько читается и ищи в потоке \r\n\r\n

А так как всегда есть шанс, что данные будут приходить по одному байту, то нужно будет реализовывать конечный автомат или использовать уже готовый http-parser, который уже отлажен и работает так же быстро, как собственный велосипед.

anonymous
()
Ответ на: комментарий от anonymous

принято заводить под это дело отдельный буфер,

куда дописываются полученные байты, после чего данные сплитятся на \n(\r), и заганяютя в список, а уже в списке ищутся нужные данные, будь то контент длинна или еще что то это в простом варианте

Или можно реализовать конечный автомат, который будет анализировать входящий поток побайтно и никуда его не сохранять. Или использовать готовый http-parser.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.