Подтвердить что ты не робот

Программирование сокетов. Какая разница между listen() и accept()?

Я читал этот учебник, чтобы узнать о программировании сокетов. Кажется, что системные вызовы listen() и accept() делают то же самое, что блокирует и ждет, пока клиент подключится к сокету, созданному с системным вызовом socket(). Зачем для этого нужны два отдельных шага? Почему бы просто не использовать один системный вызов?

Кстати, я задал этот вопрос и нашел похожие вопросы, но ни один из ответов не был удовлетворительным. Например, один из них сказал, что accept() создает сокет, что не имеет смысла, поскольку я знаю, что сокет создан socket().

4b9b3361

Ответ 1

Функция listen() в основном устанавливает флаг во внутренней структуре сокета, обозначающий сокет как пассивный прослушивающий сокет, который можно вызвать accept on. Он открывает связанный порт, поэтому сокет может начать получать соединения от клиентов.

Функция accept() просит прослушивающий сокет принять следующее входящее соединение и вернуть дескриптор сокета для этого соединения. Таким образом, в некотором смысле accept() создает сокет, а не тот, который вы используете для listen() для входящих подключений.

Ответ 2

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

Ответ 3

В приведенных выше двух ответах четко указано различие между приемом и прослушиванием. Чтобы ответить на другой вопрос - зачем нам две отдельные функции?

Один вариант использования, например, если вы хотите протестировать только доступный/доступный порт, вы можете сделать это, просто прослушивая порт и затем закрывая его, не принимая никаких соединений.

Например, https://github.com/coolaj86/golang-test-port использует прослушивание для проверки доступности порта.