Редизайн Networking TS

dreverser
dreverser

Из того что я смотрел предлагаемый в стандарт Networking TS это практически тот же самый asio из boost'a

Вот только в бусте он asio(асинхронный IO и для сериала, девайса, сети) а предлагаемый в стандарт он почему то весь превращается в Networking

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

Очень кратко по тому что я вижу из последнего Networking TS http://en.cppreference.com/w/cpp/experimental

1)

<buffer> вытянуть из пространства net/ и втянуть в стандарт отдельным независимым пропозлом, это всего лишь байтстримовый поток.

В который можно писать в конец, и читать сначала. Помоему не хватает только метода avalible() который скажет длинну от прочитанного до записаного (аналог из QT). Убрать из него все зависимости на реактор если они есть. Должна быть возможность использовать <buffer> как независимую от реактора сущность. Асинхронка если она сильно прибита к <buffer> нужно переместить в один из файлов реактора(io_context).

2)

<io_context> <executor> <timer> вытянуть из пространства net/ и втянуть в стандарт отдельным независимым пропозлом. Это асинхронный IO, он имеет отношение не только к нетворкингу, но и к IO девайсов. В него же добавиться возможность работать асинхронно с дескрипторами через <buffer>. Все зависимости на сокеты если они есть должны быть убранны из реактора.

3)

<socket> убирается жесткая зависимость на реактор (io_context) в конструкторе. А вся асинхронка переходит в отдельную сущность к примеру async_socket либо как то оборачивается в шаблон. <socket> <internet> остаются в пространстве net. 

19
рейтинг
10 комментариев
Виктор Губин

ИМХО asio вообще не стоит стандартизировать в том виде в котором она есть.

Недостатки:

Очень сложный API

Пространства имен в 4-ре уровня, скажем boost::asio::ip::tcp к тому-же не бывает непонятно в конце цепочки пространство имен или имя типа.

experimental::net::v1::ip::std - как этим вообще пользоватся ? 

Множество служебных классов 

например открытие клиентского сокета:

    boost::asio::io_context io_context;
    boost::asio::ip::tcp::resolver resolver(io_context);
    boost::asio::ip::tcp::resolver::results_type endponints = resolver.resolve("localhost", "http");
    boost::asio::ip::tcp::socket socket(io_context);
    boost::asio::connect(socket, endpoints);

Тоже в С:

  struct addrinfo hints = {AF_UNSPEC,SOCK_STREAM};
  struct addrinfo *res;
getaddrinfo("localhost","80", &hints, &res); int s = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
  connect(s,res->ai_addr,res->ai_addrlen); 

Тоже в Java:

Socket socket = new Socket("localhost", 80);
InputStream is = socket.getInputStream();

И ничего не мешает сделать 2-х строковый вариант в объектно-ориентированном С++

Строковые константы типа "http" - зачем ?

Отдельные сущьности для ip_v4 и ip_v6

  asio::tcp::endpoint endpoint(asio::tcp::v4(), "localhost" ));

  asio::tcp::endpoint endpoint(asio::tcp::v6(), "localhost" ));

От объектно-ориентированной билиотеки подобного рода вещей не ждешь.

 

Современная сетьевая библиотека без поддержки защищенных соединений (SSL/TLS) выглядит странно.

Виктор Губин
yndx-antoshkka

Напишу письмо авторам Networking TS, послушаем что они скажут по вашим замечаниями.

yndx-antoshkka
Andrey Davydov

Пункт 2, как я понимаю, автоматически следует из Executors TS, а Networking TS зависит от и будет переделан под Executors TS.

Andrey Davydov
yndx-antoshkka

Поговорил с авторами.

Пункты 1 и 2 будут решены во время слияния TS в стандарт. Я предложил убрать namespace net:: в принципе, чтобы буферы, таймеры, база для соектов и прочие вещи оказались в namespace std, а всё что связано с сетью - в namespace std::ip. Возражений не последовало. Свзяей между буфером и асинхронностью нет.

По поводу пункта 3. Есть подозрение, что не нравится не столько связь сокетов с io_context, сколько то что в текущей имплементации конструктор io_context достаточно тяжёлый, с динамическими аллокациями и т.п. Автор предлагает продемонстрировать возможность создания zero overhead имплементации io_context. Интересно? Или нужно именно оторвать сокеты от io_context?

yndx-antoshkka
Обновлено 
dreverser

Мне asio тоже не нравится, в большей степени из за его тяжелой имплементации.

Но хочу я или нет, я вижу что asio все равно втянут в стандарт. Так почему бы не по критиковать в каком виде он в стандарте будет выглядеть более логичным.

И я надеюсь что стандарт оговаривает интерфейс а не имплементацию.

И каждый отдельный компилятор напишет свои имплементации и имплементация asio не войдет во все компиляторы.

 

Вот от части из за таких сложностей АПИ многие и пишут свои велосипеды.

 

Пункт два уже разбили. Конкурент группа забрала екзекуторы в отдельный пропозл.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0443r5.html

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0761r2.pdf

 

В networking TS мне не нравится что это обсуждается в целом одним пучком. Но если они дали добро на разбиение на части в финальной коммите то хорошо.

Буферы связаны с ректором через асинхронные операции.

"17 Buffer-oriented streams"

Я не смотрел имплементацию. Но не понятно эти streams шаблонные и никак не прибитые к буферам или там какой то интерфейс и он прибит к реактору ?

И где объявлены эти самые буферы. В файле буфера или где то в отдельном файле ?

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

 

По сокетам аналогично. Если как я понял буферы не прибиты к реактору. А асинхронка на шаблонах, То почему так же не сделать и с сокетами ?

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

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

Хочет кто то юзать прибитыми к конструктору сокеты. Ну ок, пусть в стандарт введут async_socket унаследованый от сокета, где в конструкторе будет реактор.

Хотя у меня тут же вопрос. А почему тогда не сделать async_buffer ? Ну или опять же, не плодить async_socket а сделать шаблоны асинхронки как это сделано для буфера.

dreverser
dreverser

Может вместо "Buffer oriented streams" сделать "async oriented streams" ?  которые смогут работать и для буферов и для сокетов. Тогда надобность в реакторе для конструктора сокета отпадает. И сокет становится таким же легким как и буфер.

dreverser
dreverser

Про отцепили екзекуторс вот ссылка

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0958r0.html

dreverser
yndx-antoshkka

Поискал embedded устройства с сетью, на которых нет асинхнонной работы с соединениями. Не нашёл. Нашёл лишь примеры embedded устройств на которых сетевое взаимодействие выполняется очень похоже на Networking TS.

Никаких упоминаний реактора, проактора и прочих деталей реализации в io_context (и в Networking TS) не нашел. Проблем с внедрением на embedded не вижу.

Набросал интерфейс с разделёнными sync и async классами, где второе наследуется от первого. Получилось переусложнённо и не красиво.

Набросал интерфейс где async классы не обладает синхронными методами. Пострадал use case, кодга после асинхронной операции мы синхронно забираем данные из сокета, зная что данные в сокете уже есть (классический реактор). Итог: стало сильно хуже.

 

В связи со всем выше перечисленными вопрос: для чего вы хотите пункт 3) и как именно предлагаете его реализовывать?

yndx-antoshkka
dreverser

В контекте моих мыслей реактор = io_context  и все что у него под капотом

asio сам по себе является реактором в большинстве имплементаций и проактором только для iocp виндового.

На мой взгляд asio усложнена изза ее интрузивности сокета и таймера.

Основная мыль была не в том что бы дать отдельно блочный и асинхронный сокет. А в том что бы дать простую сущность типа socket  в которой только пару полей - хендл и ошибка. и методы send/receive/sendAddress/receiveAddress/open/close/итд

А уже потом этот socket заюзать во внутренностях asio. 

Зачем это и что это даст. Велосипеды все равно будут писаться. Примеров я видел достаточно. Один из тот же scraps из битторента. Так почему тем что хочет работать с "простым" сокетом не дать наконецто стандартный интерфейс ? Что бы они наконец то ушли от прямого сетевого апи ?

В asio я нашел socket_holder. Но он к сожалению ничего кроме закрыть хендл - не умеет. Я бы как минимум добавил в него все возможные методы send/receive/sendAddress/receiveAddress/open/close/итд унивицировал все socket_ops::* 

А сам socket_ops::* в большей части(особенно там где он использует хендл), перевел на обновленный socket_holder. Сам socket_ops::* тоже сильно переусложнен, но сложные части тянуть в socket_holder не стоит.

Сам socket_holder вытянул в стандарт. Пусть люди пользуются. Хватит уже этих апи.

 

Касательно самой архитектуры asio, я в размышлениях, зачем такая интрузивность. 

Все это можно было хранить и в реакторе, а после регистрации в реакторе отдавать ссылку на туже самую структуру. Сейчас очень странно видеть как async_result::get отдает void

dreverser
dreverser

Есть еще некоторые пожелания насчет имплементации ендпоинт адресов v4 v6

По моим наблюдениям за свой многолетний опыт. Трансформация IP+PORT происходит только около сетевых айпи. В остальном коде это не требуется.

Так зачем в address_v4/v6 пихать платформо зависимый тип ?

Почему бы не вставить туда обычный набор типов IP+PORT

и для трансформации в sockaddr_in/6 создать пару функций address2sock/sock2address ?

Это полностью избавит от функций network_to_host_short/host_to_network_short network_to_host_long/host_to_network_long в endpoint.

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

dreverser
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения