LINUX.ORG.RU
ФорумTalks

Сетевые пакетные сокеты

 


0

1

Вот для потоковых протоколов, например TCP, сокеты, имеющие функции send/recv полностью адекватны.

Но для датаграммных протоколов, типа UDP, IP, Ethernet, итп функция recv мне кажется совсем неверной по сути. По идее, вместо вызова recv было бы адекватнее из вызывать коллбэк, в который бы передавались данные и длина пришедшего пакета.

На низком уровне собственно так и происходит: сетевая карточка при приходе пакета дергает прерывание и тем самым вызывает обработчик прерывания, входящий в драйвер сетевой карты, который считывает очередной пакет и обрабатывает его.

Это адекватно самому протоколу ethernet.

А вот дальше все это оборачивается в recv, и как мне кажется, совершенно зря.

Точнее, сама то функция может и не так уж плоха, но вот возможности повесить коллбэк на приход пакета явно не хватает

★★★★★

Для того, чтобы можно было вызывать коллбек, нужна реализация ивент-лупа в твоём процессе. А этот уровень абстракции уже выше, чем recv (который есть просто системный вызов).

И такие реализации есть: libev, например. Или напиши свою с использованием select/poll/epoll.

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

для пакетных сокетов есть sendto/recvfrom, а send/recv с ними работают по соображениям совместимости

Harald ★★★★★ ()

Только сетевая карточка дергается на MTU (1500 байт обычно), а размер UDP пакета - до 64К.

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

Это древний спор про асинхронный vs синхронный ввод-вывод, резюме которого сводится к тому, что т.к. потоки для вызова колбеков всё равно нужны, то нефиг пихать их в ядро, берешь какой-нибудь libevent и всё.

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

Ну можно было теоретически через сигналы сделать

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

можно было теоретически через сигналы сделать

Это сильно теоретически. На сигналы ограничения не хуже чем на прерывания, типа можно изменить переменную типа atomic_t. Хотя на практике в линуксе прокатывает даже дерганье сисколлов из обработчика сигнала, но это типа нехорошо.

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

Сложно придумать что-нибудь хуже чем сигналы в UNIX.

Да ладно. Там основной косяк, что непонятно в каком треде он дернется, т.к. когда их придумывали тредов не было. Люди обычно в таких случаях просто запрещают обработку сигналов во всех потоках кроме одного.

sergej ★★★★★ ()

На низком уровне собственно так и происходит: сетевая карточка при приходе пакета дергает прерывание и тем самым вызывает обработчик прерывания, входящий в драйвер сетевой карты, который считывает очередной пакет и обрабатывает его.

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

Кроме этого, карточки могут сами склеивать несколько пакетов из потока.

Вообще, если нужно делать recv() для «UDP, IP, Ethernet, итп» очень быстро, то проще байпасить ядро. В байпасс-фреймворках тоже стараются обрабатывать пакеты пачками, это эффективнее.

возможности повесить коллбэк на приход пакета явно не хватает

Если и делать коллбэки (хотя не очень понятно зачем), то их определенно нужно делать не на одиночный пакет, а на несколько.

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

Хотя на практике в линуксе прокатывает даже дерганье сисколлов из обработчика сигнала, но это типа нехорошо.

Что значит прокатывает, такая возможность в POSIX явным образом задокументирована

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

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

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

Так и есть, NAPI сиё называется. Когда приходит первый пакет - дёргается прерывание, после чего драйвер сетевой карты запрещает прерывания, поллит вновь пришедшие пакеты и складывает их в буфер. Дальше не уверен, но думаю что поллинг продолжается до того, как hw перестанет сигнализировать о том, что есть ещё несчитанное.

Можно сделать свой коллбэк, если вызвать recv в отдельном треде в блокирующём режиме

spectral1989 ()

Всякие библиотеки event loop это и делают - ты им даешь сокет и колбэк, и они его дергают по приходу данных.

Deleted ()
Ответ на: комментарий от NeXTSTEP

Сложно придумать что-нибудь хуже чем сигналы в UNIX.

Вроде теперь с этим можно жить, т.к. придумали signalfd. Правда не знаю, есть ли он за пределами Linux.

ls-h ★★★ ()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)