Что происходит, когда мы говорим «слушай порт»? - PullRequest
23 голосов
/ 25 декабря 2010

Когда мы запускаем серверное приложение, нам всегда нужно указывать номер порта, который оно слушает.Но как этот «механизм прослушивания» реализован под капотом?

Мое текущее воображение выглядит следующим образом:

Операционная система связывает номер порта с некоторым буфером.Приложение сервера отвечает за мониторинг этого буфера.Если в этом буфере нет данных, операция прослушивания серверного приложения будет просто блокировать приложение.

Когда некоторые данные поступают из сети, операционная система будет знать , а затем проверить данные и посмотреть, ориентированы ли они на этот номер порта.И тогда он заполнит соответствующий буфер.И тогда ОС уведомит заблокированное серверное приложение, а серверное приложение получит данные и продолжит работу.

Вопрос:

  • Если приведенный выше сценарий верен,как могла система opearting знать есть данные, поступающие с провода?Это не может быть занят опрос.Это какой-то механизм на основе прерываний?

  • Если поступает слишком много данных и буфер недостаточно велик, произойдет ли потеря данных?

  • Является ли операция "прослушивание порта" действительно операцией блокировки?

Большое спасибо.

Ответы [ 4 ]

17 голосов
/ 01 января 2011

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

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

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

Что касается ваших вопросов:

  • как говорили другие: аппаратные прерывания. Сетевая карта полностью снимает дейтаграмму, прерывает и получает в памяти адрес для копирования.

  • для TCP не будет потери данных, так как во время связи всегда будет достаточно памяти. TCP имеет управление потоком, и отправитель прекратит отправку, пока у получателя не останется больше памяти. Для UDP и новых соединений TCP может быть потеря данных; отправитель обычно получает сообщение об ошибке (так как система резервирует память для принятия еще одной дейтаграммы).

  • см. Выше: прослушивание само по себе не блокирует; принять это.

7 голосов
/ 25 декабря 2010
  1. Ваше описание в основном верно, за исключением блокирующей части.Операционные системы обычно используют прерывания для обработки событий ввода-вывода, таких как поступающие сетевые пакеты, поэтому блокировать их не нужно.
  2. Да, если одновременно происходит слишком много попыток подключения, некоторые из них будут отклонены.Количество подключений к очереди указывается при вызове listen или его эквивалента.
  3. Нет, это не так.ОС вызывает событие на вашем управляющем сокете, когда приходит соединение.Вы можете выбрать блокировку во время ожидания этого события или использовать какой-либо неблокирующий (select, poll/epoll) или асинхронный механизм (перекрывающиеся порты ввода-вывода, завершающие порты).
4 голосов
/ 01 января 2011

Если приведенный выше сценарий верен, как операционная система может узнать, что данные поступают по проводам? Это не может быть занятым объединением. Это какой-то механизм на основе прерываний?

Аппаратное обеспечение сообщает об этом, отправляя событие, аппаратное прерывание вызывает запуск обработчика события.

Если поступает слишком много данных и буфер недостаточно велик, произойдет ли потеря данных?

Да, но TCP использует механизм управления окнами. ОС сообщает другому концу, сколько у нее буферов, она может делать это динамически. Так что это может начаться с того, что у меня есть 4 КБ буферов. После того, как 2k прибыл, другой конец может отправить 2k больше, но мы можем подтвердить первые 2k. Если другой конец отправит слишком много, наша ОС откажется от него. Это также скажет это замедлить и повторно признать то, что уже имеет. Когда буферы свободны, мы можем сказать другому концу, чтобы он продолжал, он отправит то, что мы не подтвердили. ОС делает все это для нас при использовании TCP, но не для UDP.

Является ли операция "прослушивание порта" действительно блокирующей операцией?

Да, но очень, очень быстро. Слушай ничего не делает, только записку для ОС. Если кто-то пытается подключиться к этому порту, это я, который будет обрабатывать это. Это принимает, что ждет этого соединения.

ОС не нужно выделять какой-либо буфер так рано. Слушай записал некоторые метаданные в таблицу os. Соединение приходит использует следующий буфер обработки соединения. Более поздние данные поступают и используют буфер данных, буфер данных не нужно выделять для каждого соединения. Множество ожидающих данных на одном соединении может привести к уменьшению доступных буферов на других соединениях. Ваша ОС может иметь политики и механизмы, чтобы сделать вещи справедливыми.

3 голосов
/ 31 декабря 2010

Что происходит, когда мы говорим "слушай порт"?

Типичная последовательность вызовов TCP-сервера:

socket() -> bind()-> listen() -> accept() -> read()/write() -> close()

Предполагается, что сокет, созданный функцией socket, является активным сокетом (который выдаст connect()). Функция listen() преобразует неподключенный сокет в пассивный сокет. Это означает, что ядро ​​должно начать принимать входящие запросы на соединение. Второй аргумент функции listen() указывает общую длину очереди для данного прослушивающего сокета из 2 очередей - (1) полная очередь соединения - 3-х стороннее рукопожатие завершено для соединения (2) очередь неполного соединения - SYN получен от клиента, ожидающего завершения 3-х стороннего TCP-квитирования

И, наконец, accept() вызывается сервером TCP для возврата следующего завершенного соединения с начала очереди завершенных соединений. Если accept () успешно, он возвращает новый дескриптор сокета, который ссылается на TCP-соединение между клиентом и сервером.

Теперь, чтобы ответить на ваш вопрос * Сетевой стек в ядре операционной системы, считывает каждый входящий IP-пакет, классифицирует пакет в соответствии с полями заголовка TCP / IP. Поступление IP-пакета по проводной линии обслуживается драйвером Ethernet как прерывание, и оттуда и далее в режиме ядра стек TCP / IP принимает

  • Что касается данных, если вы имеете в виду пакет SYN, Posix.1g имеет возможность либо игнорировать новый входящий SYN, либо отправлять RST клиенту, когда очередь подключения заполнена. Данные, поступающие после трехстороннего рукопожатия, завершаются, но до того, как серверные вызовы accept должны быть поставлены в очередь сервером TCP до размера приемного буфера подключенного сокета.

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

См. Википедию для получения более подробной информации о протоколе TCP - хендхейке, последовательности и подтверждениях для надежной передачи.

Эта книга дает очень хорошие сведения о программировании сети TCP / IP Unix и может дать более глубокое понимание этой темы.

...