Отправляли ли вы просто пакеты без тестирования хендшейка TCP соединения?
Что проверяют
Понимаете ли вы, на каком уровне сетевого стека работаете. Вопрос звучит как про опыт, но проверяет знание того, что в обычном сокете рукопожатие делает сам вызов connect(), а «отправить пакеты без хендшейка» технически означает либо UDP, либо сырые сокеты.
Как отвечать
Разложите на три случая и честно скажите, в каком работали вы.
- TCP через стандартный
socketс типомSOCK_STREAM: трёхстороннее рукопожатие SYN, SYN-ACK, ACK выполняет ядро внутриconnect(). Отдельно тестировать его нечем: если оно не прошло, вы получитеConnectionRefusedError,TimeoutErrorили ошибку разрешения имени. Попыткаsend()доconnect()даётOSError; - UDP, тип
SOCK_DGRAM: соединения нет вовсе,sendto()просто отправляет датаграмму, и успешный вызов ничего не говорит о доставке. Нужны подтверждения и повторы, их пишут руками; - сырые сокеты и
scapy: здесь действительно можно послать одиночный SYN и не завершать рукопожатие. Так делают сканирование портов и проверку правил фаервола, и для этого нужны повышенные привилегии.
Если в вашем опыте был только уровень requests или aiohttp, так и скажите: соединением там занимается библиотека и пул соединений. Это нормальный ответ, когда вы можете объяснить, что происходит уровнем ниже.
Где спотыкаются
Считают, что успешный send() означает доставку. Он возвращает число байт, скопированных в буфер отправки ядра, причём вернуть меньше запрошенного это штатное поведение, поэтому для потока используют sendall(). Факт доставки подтверждает только ответ принимающего приложения.
Второе: предлагают «отключить рукопожатие ради скорости». В SOCK_STREAM такой опции нет. Экономят иначе: переиспользованием соединений, keep-alive, отключением алгоритма Нейгла через TCP_NODELAY, а там, где потери допустимы, осознанным переходом на UDP.
Третье: проверяют соединение отдельной операцией, а потом шлют данные. Между проверкой и отправкой связь может оборваться, и узнаете вы об этом всё равно на следующей операции. Правильнее ставить таймауты через settimeout(), включать keepalive и обрабатывать ошибку записи как обычный сценарий.