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

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

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

Мое современное воображение таково:

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

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

Вопрос:

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

  • Ваше описание в основном правильное, за исключением блокирующей части. Обычно ОС используют прерывания для обработки событий ввода-вывода, таких как входящие сетевые пакеты, поэтому нет необходимости блокировать.
  • Да, если слишком много попыток соединения происходят одновременно, некоторые из них будут отскакивать. Количество подключений к очереди указывается при вызове listen или его эквиваленте.
  • Нет, это не так. При поступлении соединения ОС запускает событие в вашем гнезде управления. Вы можете заблокировать его, ожидая этого события, или можете использовать некоторые неблокирующие (select, poll/epoll) или асинхронные (перекрывающиеся порты ввода-вывода, завершающие порты) механизм.

Ответ 3

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

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

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

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

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

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

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

Ответ 4

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

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

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

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

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

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

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

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

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

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