Соединяет() блок для сокета 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-стек на стороне инициализации будет ретранслировать, но на умеренно загруженном сервере шансы высоки, этот повторно переданный пакет по-прежнему будет поступать, пока не будет принят() ожидается и будет снова сброшен, что приведет к уродливым задержкам и таймаутам подключения.