Соединяет() блок для сокета TCP?

Привет, я читаю TLPI (Интерфейс программирования Linux), у меня есть вопрос о connect().

Как я понимаю, connect() немедленно вернется, если ожидающие соединения номера listen() не достигнут "отставания". И в противном случае это блокирует. (согласно рисунку 56-2)

Но для сокета TCP он всегда будет блокироваться до тех пор, пока не будет принято accept() на стороне сервера (согласно рисунку 61-5).

Правильно ли я? Поскольку я видел это в примере кода (стр .1265), он вызывает listen() для прослушивания определенного порта, а затем вызывает connect() для этого порта ПЕРЕД вызовом accept().

Итак, connect() блокирует навсегда в этом случае, не так ли?

Спасибо!!

Ответ 1

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

Однако

  • connect() в сокете TCP - это операция блокировки, если дескриптор сокета не помещен в неблокирующий режим.

  • ОС заботится о том, чтобы квитирование TCP, когда рукопожатие завершено, connect() возвращает. (то есть, connect() не блокируется до тех пор, пока другие end-вызовы не будут принимать())

  • Успешное рукопожатие TCP будет поставлено в очередь на серверное приложение и может быть принято() в любое время позже.

Ответ 2

connect является блокирующим вызовом по умолчанию, но вы можете сделать его не блокирующим, перейдя на socket флаг SOCK_NONBLOCK.

Ответ 3

connect() до завершения трехстороннего рукопожатия TCP. Рукопожатие на стороне слушателя обрабатывается стеком TCP/IP в ядре и завершается без уведомления пользовательского процесса. Только после того, как рукопожатие завершено (и инициатор может вернуться из вызова connect() уже), accept() в пользовательском процессе может забрать новый сокет и вернуть его. Не требуется ждать принятия(), необходимого для завершения рукопожатия.

Причина проста: если у вас есть однопоточный процесс, который прослушивает подключения и требует ожидания accept() для установления соединений, вы не можете отвечать на TCP SYN при обработке другого запроса. TCP-стек на стороне инициализации будет ретранслировать, но на умеренно загруженном сервере шансы высоки, этот повторно переданный пакет по-прежнему будет поступать, пока не будет принят() ожидается и будет снова сброшен, что приведет к уродливым задержкам и таймаутам подключения.