TCP-сервер не принимает правильное количество соединений, выпущенных клиентом с небольшим объемом ожидания

Я написал простую клиентскую программу для выдачи 10000 соединений с использованием 100 потоков за очень небольшую продолжительность. И простая серверная программа с listen backlog установите значение 20 с помощью epoll, чтобы принять любое новое соединение и записать общее количество соединений. я использовал ulimit -n чтобы убедиться, что он больше, чем 20000, поэтому должно быть достаточно ресурса fd.

Но после серверной программы acceptКак 8800, 9400 (не фиксированные) соединения, он просто перестал принимать любое новое соединение. Клиент использовал блокировку connect установить соединения, и все эти 10000 вызовов connect вернул успех. Затем все зависает, больше нет пакетов (нет повторной передачи), больше нет принятого соединения.

Но как только я закрыл клиентскую программу, серверная программа начала принимать оставшиеся соединения после закрытия некоторых соединений (и в итоге приняла все 10000 соединений и закрыла все эти соединения).

Когда я изменился backlog до 100 или более, все 10000 соединений были приняты без каких-либо проблем. (так что это не проблема ресурса fd)

Я знаю, что при заполнении очереди, Linux может просто игнорировать входящие ACK трехстороннего рукопожатия, оставив соединение с клиентом установленным, но соединение с сервером все еще не установленным, а затем дайте механизму ретрансляции работать. И в итоге сервер ретранслирует SYN/ACK Пакет, клиент отвечает ACK восстановить это соединение, если доступна очередь приема сервера. Если в очереди нет свободного места, сервер игнорирует ACK снова.

Но когда я использую Wireshark для мониторинга этих повторных передач, я обнаружил, что только небольшое количество SYN/ACK произошла повторная передача (например, 100 ~ 200, что намного меньше, чем количество потерянных соединений, которое составляет от 500 до 1500), и они передаются повторно один или два раза, все меньше значения, указанного в /proc/sys/net/ipv4/tcp_synack_retries, Я осмотрел некоторые из этих ретранслируемых SYN/ACK пакеты, все из которых получены ACKс клиента. Но количество ретранслируемых SYN пакеты от клиента были большими.

Итак, каковы основные детали?

Вот мои коды:
клиент
сервер

0

Решение

Когда резерв будет заполнен и файлы cookie SYN включены, ядро ​​активирует временный режим потока SYN. Эта диаграмма показывает, как работают файлы cookie (источник):

введите описание изображения здесь

Когда SYN-флуд был активирован, все ACK, отправленные с клиента, будут сброшены. Сервер отправил только SYN / ACK и cookie клиенту, таблица кэша cookie будет намного меньше таблицы сокетов, чтобы поддерживать активное соединение.
В этом случае на стороне клиента сокет считался установленным, но на стороне сервера ничего не открывалось (полуоткрытое соединение).

Когда клиентское приложение закрывает сокет, пакет FIN с установленным флагом ACK будет отправлен на сервер с файлом cookie внутри, сервер увидит, что соединение имеет ACK, в этот момент, если резерв не заполнен, сервер будет попробуйте восстановить соединение из куки. Если файл cookie действителен (в пределах допустимого туда-обратно), сокет будет добавлен в очередь невыполненных работ и может быть обработан как обычный сокет.

Это означает, что, когда был активирован режим куки-файла SYN и очередь невыполненных заданий не заполнена, если клиент отправляет некоторые данные на сервер через полуоткрытые сокеты, функция accept () вернет новое соединение с поступлениями.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]