Сокетное программирование - сомнение API - PullRequest
1 голос
/ 06 февраля 2011

Сегодня в классе был опубликован вопрос о разработке API в программировании сокетов.

Почему функции listen () и accept () предоставляются как разные функции и не объединены в одну функцию?

Теперь, насколько я знаю, listen помечает подключенный сокет как готовый к принятию соединений и устанавливает максимальный предел для очереди входящих соединений. Если слиты accept и listen объединены, нельзя ли поддерживать такую ​​очередь?

Или есть какое-то другое объяснение?

Заранее спасибо.

Ответы [ 3 ]

4 голосов
/ 06 февраля 2011
  • listen() означает «начать прослушивание для клиентов»
  • accept() означает «принять клиента, блокируя до тех пор, пока один не подключится, если необходимо»

Это имеет смыслразделить эти два, потому что если бы они были объединены, то единственная объединенная функция заблокировала бы.Это может вызвать проблемы для неблокирующих программ ввода-вывода.

Например, давайте возьмем типичный сервер, который хочет прослушивать новые клиентские соединения, но также отслеживать существующие клиентские соединения на наличие новых сообщений.Такой сервер обычно использует неблокирующую модель ввода / вывода, чтобы он не блокировался ни на одном конкретном сокете.Таким образом, ему нужен способ «начать прослушивание» на сокете сервера, не блокируя его.Как только прослушивание на сокете сервера было инициировано, сокет сервера добавляется в группу отслеживаемых сокетов с помощью select() (в некоторых системах poll()).Вызов select() будет указывать, когда в сокете сервера находится клиент, ожидающий обработки.Затем программа может вызвать accept(), не опасаясь блокировки на этом сокете.

1 голос
/ 06 февраля 2011

Под капотом bind назначает адрес и порт дескриптору сокета. Это означает, что порт теперь зарезервирован для этого сокета, и поэтому система не сможет назначить этот порт другому приложению (исключение существует, но я не буду здесь вдаваться в подробности). Это также одноразовая операция на сокете.

Тогда listen отвечает за установление количества соединений, которые могут быть поставлены в очередь для данного дескриптора сокета, и указывает, что вы теперь готовы получать соединения.

С другой стороны, accept используется для удаления первого соединения из очереди ожидающих соединений и создания нового сокета для дальнейшей связи через него. Это может быть вызвано несколько раз, и, как правило, это. По умолчанию эта операция блокируется, если в очереди нет соединений.

Теперь предположим, что вы хотите использовать асинхронный механизм ввода-вывода (например, epoll, poll, kqueue, select и т. Д.). Если вы слушаете и принимаете один API, как бы вы указали, что данный сокет готов принимать соединения? Асинхронный механизм должен знать, что вы также хотите обрабатывать события этого типа.

Имея совершенно другую семантику, имеет смысл разделить их.

1 голос
/ 06 февраля 2011

listen(2) делает данный сокет TCP серверным сокетом , то есть создает очередь для приема запросов на подключение от клиентов.* Порт прослушивания и, возможно, IP-адрес связаны (таким образом, вам необходимо позвонить bind(2) до listen(2)).accept(2) затем фактически принимает такой запрос на подключение из этой очереди и превращает его в подключенный сокет (для двусторонней связи требуется четыре части - IP-адрес источника, номер порта источника, пункт назначенияIP-адрес и номер порта назначения - назначаются).listen(2) вызывается только один раз, тогда как accept(2) обычно вызывается несколько раз.

...