LINUX.ORG.RU

C++ парсинг протоколов. HTTP, например.


0

2

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

Например, в nginx запилена такая FSM (finite state machine), которая жрёт по 1 байту и идёт в длинный switch, где в зависимости от текущего состояния каким-то образом сжирает этот байт.

Но в реальной жизни в 99% случаев HTTP-запрос (пачка хидеров и завершающий двойной перевод строки) целиком приходит в одном пакете. То есть, при чтении из сокета в 99% случаев оказывается, что нам доступен целый запрос в буфере и FSM нам не нужен, мы можем запустить последовательность процедур, которые выцепят из этого буфера разные аспекты парсимого протокола.

Насколько большой оверхед даёт FSM в виде хождения в таблицу указателей на функции (это то, во что скомпилируется switch) на каждый байт?

Я понимаю, что FSM по-хорошему нужен. Кусок HTTP-запроса может прийти раньше второго куска. Малолетние хакеры могут захотеть посылать HTTP-запросы через nc по одной строчке и это выдержит nginx. Но в реальной жизни целый запрос обычно валится в виде одного пакета.

★☆

Последнее исправление: kiverattes (всего исправлений: 2)
Ответ на: комментарий от anonymous8

да, спасибо, я в курсе что такое switch/case, я спрашивал как, конкретно, предполагается использовать switch/case при парсаньи html?

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

ведь slave в английском происходит от «славянин».

да, есть такая популярная поцтриотическая теория (исследования a-la Задорнов), однако научные исследования говорят нет, не происходит.

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

Наверное, он хочет сказать в потоко-ориентированных нижележащих протоколах не может (не должна) рушиться последовательность передачи.

Но исходя из моего опыта работы программистом. Рушиться она очень даже может. И естественно потоковый протокол тут не виноват. Рушиться может выше него. Например, удаленная сторона может быть многопоточной и плохо синхронизированной. Один ее тред может отработать быстрее других и соответственно очередность пакетов порушится. Красивые книжки - это хорошо. Но вот реальность программисткая - она совсем другая.

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

Но исходя из моего опыта работы программистом. Рушиться она очень даже может. И естественно потоковый протокол тут не виноват. Рушиться может выше него. Например, удаленная сторона может быть многопоточной и плохо синхронизированной. Один ее тред может отработать быстрее других и соответственно очередность пакетов порушится. Красивые книжки - это хорошо. Но вот реальность программисткая - она совсем другая.

тогда это неправильный запрос от некорректного приложения и надо в ответ посылать код ошибки и дропать соединение

Harald ★★★★★
()

а смысл парсить по байту? подождал, пока \n\n или \n\r\n\r придёт и обработал сразу. получил таймаут или лишние байты (сверх конфига) - закрыл соединение, пометил буфер под заголовки как пустой.

Прыжки по адресу на каждый байт с вызовом случайной функции убьют конвейер. Там проверки правильно/неправильно, можно и хинты для бранчей поставить.

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

а смысл парсить по байту?

Да никто не парсит по байту. Это ТС как-то криво излагает. В nginx парсер парсит кусками данных. Прочитал сколько пришло, отдаешь парсеру, он парсит и в процессе вызывает callback-и

anonymous
()

Но в реальной жизни в 99% случаев HTTP-запрос (пачка хидеров и завершающий двойной перевод строки) целиком приходит в одном пакете.

Верно в 99%, не в 100%, а именно в 99%. Оставшийся один процент случаев игнорировать нельзя.

запилена такая FSM (finite state machine), которая жрёт по 1 байту и идёт в длинный switch

Ну не обязательно один байт, количество байт может зависеть от текущего состояния.

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