Понимание интерфейса BSD - PullRequest
1 голос
/ 29 июня 2011

Я пытаюсь понять, как события в интерфейсе сокета BSD переводят в состояние TCP-соединения. В частности, я пытаюсь понять, на каком этапе процесса подключения accept() возвращается на стороне сервера

  1. клиент отправляет SYN
  2. сервер отправляет SYN + ACK
  3. клиент отправляет ACK

На каком из этих шагов accept() возвращает?

Ответы [ 2 ]

5 голосов
/ 29 июня 2011

accept возвращается, когда соединение установлено. Соединение завершено после того, как клиент отправит свой ACK .

accept дает вам сокет, по которому вы можете общаться. Конечно, вы знаете, вы не можете общаться, пока не будет установлено соединение. И соединение не может быть установлено до рукопожатия.

Не имеет смысла возвращаться, пока клиент не почувствует свой ACK. Вполне возможно, что он ничего не скажет после первоначального SYN. ​​

1 голос
/ 29 июня 2011

Код стека TCP / IP в ядре обычно [1] завершает трехстороннее рукопожатие полностью без вмешательства какого-либо пользовательского кода. Все три шага, которые вы перечисляете, происходят за до accept() возврата. Действительно, они могут произойти до того, как accept() даже будет вызван!

Когда вы указываете стеку listen() для соединений через определенный порт TCP, вы передаете параметр backlog, который сообщает ядру, сколько соединений он может молча принимать от имени вашей программы одновременно. Именно эта очередь используется, когда ядро ​​автоматически принимает новые запросы на соединение, и там они удерживаются до тех пор, пока ваша программа не получит их accept(). Когда при вызове accept() имеется одно или несколько подключений в очереди прослушивания, все, что происходит, это то, что самое старое удаляется из очереди и связывается с новым сокетом. [2]

Другими словами, если ваша программа вызывает listen(sd, 5), то входит в бесконечный цикл бездействия, так что она никогда не вызывает accept(), с точки зрения клиентов пять одновременных запросов клиентского соединения будут выполнены успешно. Шестой запрос на подключение будет остановлен на первом пакете SYN, пока программа, владеющая портом TCP, не вызовет accept(), или один из других клиентов не разорвет свое соединение.


[1] Брандмауэр и другие модификации стека, конечно, могут изменить это поведение. Я говорю только о поведении стека сокетов BSD по умолчанию.

[2] Если нет никаких соединений, ожидающих в очереди, когда вы вызываете accept(), он блокируется по умолчанию, если сокет слушателя не был установлен неблокирующим, в этом случае он возвращает -1 и errno EWOULDBLOCK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...