LINUX.ORG.RU

Лыжи не едут или ab2 странный?

 ab2, , ,


0

1

Есть крайне примитивный TCP сервер на С. Знаю, что говнокод, реальный код несколько иной, с потоками и парсингом HTTP, но данный тестовый пример неплохо иллюстрирует суть проблемы. Я тестирую его с помощью ab2 (apache benchmark).

Проблема первая. При параметре -с 4 у ab2 (4 параллельных запроса) - первые два запроса обрабатываются практически мгновенно, а вот на третьем очень долго висит recv. Может ли в принципе быть проблема в моем коде, или же виноват ab2, не отправляющий по какой-то причине данные?

Проблема втораяРешено. В коде можно заметить обработчик SIGINT, закрывающий socket. Если запустить программу и тут же убить по Ctrl-C, затем запустить снова - все будет работать нормально. Если же послать ей, перед убийством, хотя бы один запрос - при следующем запуске bind ругнется на Address already in use. Разве закрытие слушающего сокета не должно приводить к освобождению адреса?

★★★

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

Читанул. Также таки нашел про TIME_WAIT, так что вторая проблема неактуальна. Спасибо.

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

Спасибо, проверил с httperf, и правда работает. Еще раз повторюсь, реальный код получает и шлет HTTP, это - просто тесткейс.

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

write(socket, msg, sizeof(msg)-1);

В реальном коде 1 тоже безо всякой причины вычитается? Там он ошибок не возвращает? В строчке Errors: total x client-timo x ... всё по нолям? Проверь на всякий случай

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

На реальном коде -1 не вычитается, здесь это нужно, чтобы нулевой байт не отправлялся.
В строчке Errors - ничего нет, т.к. там отправляется валидный HTTP-ответ и поддерживается Keep-Alive (без него httperf будет ругаться на connreset).
В целом - спасибо, думаю, проблема в ab.

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

На реальном коде -1 не вычитается, здесь это нужно, чтобы нулевой байт не отправлялся.

Чё-то мне показалось, что sizeof его не считает. Ошибся.]

поддерживается Keep-Alive (без него httperf будет ругаться на connreset).

Чего-чего? Закрытое соединение - никак не reset. Смотри, что он у меня дает:

> httperf --port 12345 --num-conns 200
httperf --client=0/1 --server=localhost --port=12345 --uri=/ --send-buffer=4096 --recv-buffer=16384 --num-conns=200 -
-num-calls=1                                                                                                        
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 1

Total: connections 200 requests 200 replies 200 test-duration 0.035 s

Connection rate: 5748.3 conn/s (0.2 ms/conn, <=1 concurrent connections)
Connection time [ms]: min 0.1 avg 0.2 max 1.0 median 0.5 stddev 0.1
Connection time [ms]: connect 0.1
Connection length [replies/conn]: 1.000

Request rate: 5748.3 req/s (0.2 ms/req)
Request size [B]: 62.0

Reply rate [replies/s]: min 0.0 avg 0.0 max 0.0 stddev 0.0 (0 samples)
Reply time [ms]: response 0.1 transfer 0.0
Reply size [B]: header 19.0 content 0.0 footer 0.0 (total 19.0)
Reply status: 1xx=0 2xx=200 3xx=0 4xx=0 5xx=0

CPU time [s]: user 0.00 system 0.03 (user 0.0% system 98.0% total 98.0%)
Net I/O: 454.7 KB/s (3.7*10^6 bps)

Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
> exit
lispfuerimmer
()
Ответ на: комментарий от lispfuerimmer

Ответ такой:

const char msg[] = {'H', 'T', 'T', 'P', '/', '1', '.', '0', ' ', '2', '0', \ '0', ' ', 'O', 'K', 13, 10, 13, 10};

Но смотри, может с другими версиями протоколов нужно слать что-то ещё, чего он не получил и дал reset. Но отсутствие keep-alive вряд ли повод для reset.

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

Думаю, тут дело в том, что у тебя --num-calls=1.
Если сделать больше - он попытается сделать второй реквест через это уже созданное соединение, без keep-alive - обломится (как я понял, он игнорирует заголовок Connection: Close). И, соотв., выдаст connreset. По крайней мере, мне показалось именно так.

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