Я пытаюсь понять, как операционные системы обычно осуществляют повторную сборку сетевых запросов. Из моего лучшего понимания верно следующее:

HTTP-запрос делается на прикладном уровне с использованием некоторой библиотеки HTTP. Эта HTTP-библиотека действительно является оболочкой для некоторой реализации сокетов ОС.

"Передающий" сокет создается с использованием назначения и источника HTTP-запроса.

"Принимающий" сокет создается с использованием IP-адреса устройства и рандомизированного (свободного) порта.

HTTP-сообщение "отправляется" с использованием "передающего" файлового дескриптора сокета.

Метод "send" сокета отправляет сообщение реализации TCP операционной системы.

Реализация TCP сегментирует сообщение HTTP, добавляя порт назначения (предоставленный при создании экземпляра сокета) и порт источника. (Я предполагаю, что это каким-то образом передается в зависимости от реализации.) После того, как HTTP-сообщение было сегментировано и к нему добавлены заголовки TCP, сегменты TCP затем передаются в реализацию IP ОС.

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

Затем IP-пакеты упаковываются в заголовки Ethernet, отправляются на маршрутизатор, отправляются на сервер, сервер обрабатывает запрос и отправляет ответ.

Здесь мое понимание нарушается в отношении того, что именно происходит в процессе сборки.

Как ответ возвращается в приемный буфер "принимающего" сокета, чаще после того, как IP-пакет возвращается на устройство?

Очевидно, что заголовки сбрасываются, но какие шаги предпринимаются, чтобы вернуть его конкретно в приемный буфер "принимающего" сокета, а затем из сокета обратно в приложение?

PS Я надеюсь на более подробную техническую реализацию, чем просто "IP повторно собирает его" или "TCP повторно собирает его" и передает его на следующий уровень. Я надеюсь понять, как именно это происходит, а не только теоретически (хотя я понимаю, что это зависит от ОС).

Редактировать:

Чтобы внести ясность в предмет, я хотел бы отметить мои ссылки на сокет и любой метод сокета, относящийся к ОС Linux.

2 ответа2

1

Хорошая находка от Mike Penningtion (в комментариях), где можно найти подробное техническое описание пути запроса по сетевому стеку и резервному копированию (специфично для ОС Linux 2005).

Более подробный обзор, из которого были извлечены следующие шаги:

Обратите внимание, что хотя перечисленные шаги не так подробны, как в документе, упомянутом выше, примерно эти шаги:

ОС имеет выделенный файловый дескриптор для порта Ethernet Ethernet,

The rx ring is a ring in the kernel memory where the network card transfers the incoming packet through DMA. The raw data which is stored in the rx ring structure is either copied into a sk buff structure.

Затем запускается ISR для перемещения пакета на сетевой уровень. Обратите внимание, что здесь выбирается, обрабатывать ли пакет или пересылать его (что было интересно, так как я думаю, возможно, именно так работает включение пересылки, например, для VPN)

Если он действителен, он переходит на IP-уровень. Он проверяет свой протокол (из заголовка IP) и, если это протокол TCP, вызывает tcp v4 rcv , тем самым переходя на уровень TCP.

И эта часть имеет решающее значение:

The next step for this function is to find an open socket for this incoming packet,

это делается путем вызова tcp v4 lookup в следующем сегменте кода:

sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source,
skb->nh.iph->daddr, ntohs(th->dest),
tcp_v4_iif(skb));

По сути, я понял, что существует LUT, сопоставляющий сокет TCP с адресом / портом источника и получателя соединения сокета, как указано в этом вызове функции.

Если существует допустимый сокет, данные помещаются в tcp_data_queue чтобы продолжить стек для использования приложения.

0

(из комментариев)

Я получаю инкапсуляцию. Допустим, в ОС есть выделенный дескриптор файла, открытый на выделенном порту Rx Ethernet. Он удаляет заголовок Ethernet с фрейма и передает его в некоторую функцию анализа IP, чтобы удалить IP-адрес назначения. Он помещает это в некоторую структуру, а затем отправляет ее и структуру на уровень TCP. Здесь он удаляет его из порта назначения и помещает его в ту же структуру. Здесь должно быть некоторое сопоставление с дескриптором файла сокетов на основе порта и ip, чтобы поместить данные в буфер, назначенный дескриптору файла. Это мой лучший способ пойти на это. Но я хотел бы знать, что на самом деле происходит.

Довольно старая версия того, что вы ищете, находится здесь: сетевой стек Linux. Я пытаюсь найти что-то более новое, чем описание 2005 года, потому что некоторые изменения в Linux изменились с тех пор. Большая часть информации о буферизации сокетов хранится в структуре, называемой sk_buff, которая представляет собой структуру linux, которая содержит указатели на дескриптор сокета TCP, а также все буферы чтения / записи сокетов.

Когда драйвер сетевой карты linux получает информацию от сетевой карты на заданном сокете, он ищет буферное пространство в экземпляре sk_buff (с именем skb) и выгружает данные в буферы, на которые указывает skb .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .