LINUX.ORG.RU

Tcp в Linux

 , ,


0

3

Объясните пожалуйста связаны ли описатели(fd) сокета и соединения. И если да то как? Моё предположение сокет фильтрует пакеты и распределяет их по соединениям. Тогда как соединение их принимает от другого описателя(fd сокета)?

Ещё: если соединение отправляет данные через сокет, то откуда система знает что соединение хочет что-то отправить? Каждый раз проходится по всем соединениям? Или там используются таймеры?

Подразумевается что сокет = socket(), а соединение = connect/accept().



Последнее исправление: Ingvar2145 (всего исправлений: 1)

откуда система знает

Работа с сокетами целиком лежит на ядре. Сокет ничего не фильтрует. Сокета не существует физически - это абстракция для работы с оперативной памятью. То что он в системе представляен как файл - часть концепции «в Linux всё файлы». Работа с сетью на низком уровне выглядит так: Linux, пожалуйста, открой соединение и отправь данные.

rtxtxtrx
()

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

mittorn ★★★★★
()

sockfd_lookup(9) возвращает struct socket*, т.е. соответствие однозначное.

То что возвращает accept - это новый сокет и новый fd, который к старому имеет довольно мало отношения.

connect по сути (если опустить syn/ack и всякие мелочи) просто запоминает удалённый адрес. Его можно сделать и для udp чтоб не указывать каждый раз куда слать udp-пакет.

sergej ★★★★★
()
Ответ на: комментарий от rtxtxtrx

То что он в системе представляен как файл - часть концепции «в Linux всё файлы».

Ну только сокеты это не файлы, у них свой набор сисколов и по сути они лютое нарушение этой концепции. С них-то все и началось.

cumvillain
()

В общем случае не связаны. Ведь после вызова socket и до вызова connect/accept fd есть, а соединения нет.

откуда система знает что соединение хочет что-то отправить

Соединение само по себе ничего не хочет отправить. Хочет отправить либо процесс, для этого он вызывает один из syscall, либо удаленный хост. В последнем случае сетевая карта получает пакет, кладет его в буфер и отправляет специальный сигнал ядру. Ядро читает буфер, парсит содержимое, определяет к какому соединению оно относится(если относится. Бывают пакеты, которые нужно форвардить другому хосту, или просто заблудившиеся пакеты) и ставит полученные данные в очередь связанную с этим соединением.

cobold ★★★★★
()

Объясните пожалуйста связаны ли описатели(fd) сокета и соединения. И если да то как?

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

TCP Соединение - это структура данных внутри ядра linux, точнее в его части называемой «стек TCP». «стек» - это прост куча кода/функций/структур, которые расположены в ядре и делают так, чтобы TCP физически существовало и работало. Стек TCP - это физически такой код на Си, который напрограммировали бородатые программисты, который реализует коннекты, порты, и всё что мы знаем про TCP.

сокет фильтрует пакеты и распределяет их по соединениям

Фильтрует «стек TCP». Когда пакет приходит в сетевуху, драйвер сетевухи просыпается по прерыванию и создаёт в ядре структуру данных, описывающую этот пакет. Эта структура далее обрабатывается ядром в «сетевой подсистеме ядра», которая уже много чего делает: там и всякие фейрволы и понимание кому он пришёл (какому сокету/соединению) или самому ядру. Ядро например на пинги отвечает PONG пакетами само.

В сетевуху пришёл пакет: драйвер сетевухи проснулся, сделал «пакет» структуру данных, отдал ядру. Ядро поняло, что это пакет не какой-то мусорный, а TCP. Далее оно поняло, на какой порт пришёл этот пакет и от какого исходящего IP:PORT. Далее оно поняло, что локальный порт, на который пакет пришёл, был открыт в результате connect() таким-то приложением и это приложение получит эти данные через данный fd.

Наоборот то же самое: приложение записало данные в fd, ядро осознало что это fd указывает на соединение, что соединение живо, что возможность отправки есть (window не исчерпан, congestion control норм и т.п.), формирует пакет TCP и отдаёт драйверу сетевухи.

если соединение отправляет данные через сокет, то откуда система знает что соединение хочет что-то отправить

Система всегда знает что-то потому, что кто-то сделал системный вызов или потому, что произошло прерывание аппаратное или другое. В любом случае, в систему явно «заходят». Кто-то. Или приложение или драйвер сетевухи или таймер какой-то аппаратный. Если приложение пишет данные в сокет, то ядро понимает, что этот сокет (fd) указывает внутри ядра на структуру данных, которая описывает соединение TCP например. Соединение - это структура данных о том, какой IP:PORT с каким другим IP:PORT «соеденины» сейчас и какой там статус переданности потока и прочих настроек. В благоприятном исходе, ядро сформирует TCP пакет и отдаст драйверу сетевухи. Обратно работает похоже, как написано выше.

Каждый раз проходится по всем соединениям?

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

Или там используются таймеры?

Таймеры - они везде используются. Таймер - это обычно физически структура данных типа «heap», она же «двоичная куча». Таймеры везде есть и они полезны просто потому, чтобы закрывать забытые соединения, абоненты по которым давно померли, например (keep-alive пакеты в TCP например можно погуглить).

lesopilorama
()
Последнее исправление: lesopilorama (всего исправлений: 4)
Ответ на: комментарий от lesopilorama

Нето, у tcp сокета есть буфер, представь что он заполнен. Вот скажи: ядро вызывает у него функцию типа update чтобы он отправил что-то? То есть все соединения это новые сокеты и они все на одном порту? Тогда кто распределяет пакеты между ними? Если бы они проходили через listen сокет и он бы их распределял по соединениям…

Ingvar2145
() автор топика
Ответ на: комментарий от lesopilorama

Мне кажется что ты чат гпт. Ты ни на один вопрос прямо не ответил. Я спросил: «(ядро)Каждый раз проходится по всем соединениям?» а ты говоришь: «Нет, обычно используются умные структуры данных, типа хеш-таблиц, деревьев поиска и прочего такого.» Я же не спрашивал что там используется. Я спросил как ядро обновляет состояние соединения, каждый раз проходится по всем соединениям и вызывает update???

Ещё один вопрос: «Объясните пожалуйста связаны ли описатели(fd) сокета и соединения. И если да то как?» Ты говоришь - связаны. И даёшь определение какоето. Как СВЯЗАНЫ ТО???

Скажи често: чат гпт.

Ingvar2145
() автор топика
Ответ на: комментарий от Ingvar2145

Нето, у tcp сокета есть буфер, представь что он заполнен. Вот скажи: ядро вызывает у него функцию типа update чтобы он отправил что-то? То есть все соединения это новые сокеты и они все на одном порту? Тогда кто распределяет пакеты между ними? Если бы они проходили через listen сокет и он бы их распределял по соединениям…

Ни одной сущности, которую ты тут упоминаешь, в реальности не существует. Нельзя ответить на вопросы «да/нет» о том, чего нет. Функция «update» у буфера TCP-сокета, это что? Дайте код почитать.

lesopilorama
()
Ответ на: комментарий от Ingvar2145

Мне кажется что ты чат гпт. Ты ни на один вопрос прямо не ответил. Я спросил: «(ядро)Каждый раз проходится по всем соединениям?» а ты говоришь: «Нет, обычно используются умные структуры данных, типа хеш-таблиц, деревьев поиска и прочего такого.» Я же не спрашивал что там используется. Я спросил как ядро обновляет состояние соединения, каждый раз проходится по всем соединениям и вызывает update???

Ещё один вопрос: «Объясните пожалуйста связаны ли описатели(fd) сокета и соединения. И если да то как?» Ты говоришь - связаны. И даёшь определение какоето. Как СВЯЗАНЫ ТО???

Скажи често: чат гпт.

Нет, оно не проходит каждый раз по всем соединениям, это ведь было тебе сказано, чо ты разнылся-то.

Как СВЯЗАНЫ ТО???

Очевидно, связаны логически! В коде и структурах данных. Как ещё ответить-то, код тебе привести или чо. Вопросы у тебя странные наркоманские конечно, надо признать!

Лучше всего будет почитать кодик ядреца линукса, там же всё написано. И как чо связано и как чо работает. А чо ты там спросил - это неинтересно, потому что вопросы жесть какие неграмотные. Но видишь даже на них ты получаешь ответы, так что друзья тебя не бросают в беде!

lesopilorama
()
Последнее исправление: lesopilorama (всего исправлений: 3)
Ответ на: комментарий от Ingvar2145

int fd = accept()

Да, это fd сокета, а не соединения. Соединение - это абстракция TCP, которая «присобачена» внутри ядра к этому сокету, а приложение видит сугубо сокет, а не соединение. Приложение не видит никаких соединений, приложение видит только сокеты.

lesopilorama
()
Последнее исправление: lesopilorama (всего исправлений: 2)

По теме рекомендую книги Стивенса («Сетевое программирование» или как-то так). И книгу Мориса Баха Design of the UNIX Operating System, наверняка есть в переводе. Последняя про то ли SystemV, то ли BSD, но такие базовые понятия, как дескриптор и проч. до сих пор применимы и для Linux как UNIX-like системы.

seiken ★★★★★
()