Постоянное соединение HTTP

Пытаясь реализовать простой HTTP-сервер на C, используя интерфейс сокетов Linux, я столкнулся с некоторыми трудностями, связанными с определенной функцией, а именно с постоянными соединениями. Относительно легко отправлять один файл за раз с отдельными TCP-соединениями, но это не кажется эффективным решением (например, с учетом нескольких рукопожатий). В любом случае, сервер должен обрабатывать несколько запросов (HTML, CSS, изображения) в течение одного TCP-соединения. Не могли бы вы дать мне несколько подсказок, как подойти к проблеме?

1 ответ

Решение

Это довольно просто - просто не закрывайте соединение TCP после того, как напишите ответ.

Есть два способа сделать это, конвейерный и не конвейерный.

В не конвейерной реализации вы читаете один http-запрос в сокете, обрабатываете его, записываете обратно из сокета и затем пытаетесь прочитать другой. Продолжайте делать это до тех пор, пока удаленная сторона не закроет сокет, или закройте его самостоятельно после того, как вы перестанете получать запросы на сокет через 10 секунд.

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

Вам не нужно это делать, но вы можете объявить, что поддерживает постоянные соединения и конвейеризацию, добавив в свои ответы следующий заголовок:

Connection: Keep-Alive

Прочитайте это: http://en.wikipedia.org/wiki/HTTP_persistent_connection

Кстати, на практике не существует огромных преимуществ для постоянных соединений. Затраты на управление рукопожатием очень малы по сравнению с затратами времени на чтение и запись данных в сетевые сокеты. Есть некоторые споры о преимуществах производительности постоянных соединений. С одной стороны, под большой нагрузкой сохранение открытых соединений означает гораздо меньше сокетов в вашей системе в TIME_WAIT. С другой стороны, поскольку вы сохраняете сокет открытым в течение 10 секунд, в любой момент времени у вас будет открыто гораздо больше сокетов, чем в непостоянном режиме.

Если вы заинтересованы в улучшении производительности самописного сервера - лучшее, что вы можете сделать для повышения производительности сетевого "интерфейса" вашего сервера, - это внедрить систему управления сокетами на основе событий. Посмотрите на libev и eventlib.

Другие вопросы по тегам