Внешняя компонента как REST-API-компонента...

01.11.21

Разработка - Разработка внешних компонент

...и совсем немного кода на С[++]...

Всем привет!

 

ВВЕДЕНИЕ

Я в последнее время делал несколько проектов на Python, суть которых сводилась к внешнему сервису, работающему как очередь оборудования и механизм контроля. Но Python - это хоть и очень просто, но не так быстро, поэтому время от времени я пытался найти, как сделать какой-нить сервис на С[++] (плюсы в скобках как бы намекают, что от плюсов там по большому счету только int перед main). В итоге нашел, что позволило мне все свои механизмы, написанные на Python, достаточно легко и непринужденно переработать в механизмы, работающие на С++.

 

БИБЛИОТЕКА RESTBED

Периодически набирая в гуглах что-то типа "HTTP-сервер на С++", я натыкался на разные решения с костылями и палками, но в последний раз наткнулся на отличную (на мой скромный взгляд) библиотеку, которая достаточно просто позволяет организовать HTTP-сервис, и при этом (и это было важно) существует и отлично работает даже на DEBIAN для Rispberry PI (ниже приведу сравнительный тест).

Сама по себе библиотека очень проста и в сути своей оперирует всего несколькими сущностями: настройкой соединения и ссылкой на сервисы. У библиотеки достаточно большой функционал (включая авторизацию, SSL/HTTPS, многопоточность и все то, что еще может нам потребоваться).

 

ПРИМЕР ПРОСТОГО СЕРВИСА

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

Для начала установим соответствующую библиотеку (для Linux, как это сделать в винде - я без понятия, если, конечно, что не WSL[2]).

sudo apt install librestbed-dev librestbed0

Тут у нас два пакета - сама библиотека и ее заголовочные файлы для разработчиков.

Дальше при сборке нам достаточно будет указать опцию "-lrestbed" и все.

Напишем простой код:

 

ЗАГОЛОВКИ

#include <stdlib.h>
#include <map>
#include <string>
#include <memory>
#include <cstdlib>
#include <restbed>

1. Стандартная библиотека - нужна нам для преобразования параметра командной строки в число функцией atoi (для указания номера порта, на котором весить сервис).

2. Map - "ассоциативный массив", который всегда упорядочен по ключу. Скорость доступа к элементуO( Log2N ).

3. Строки - куда без них...

4. Умные указатели - в нашем случае это shared_ptr, который... Сами где-нить прочитайте, а то это может быть надолго. В нашем случае понимать всю суть этого не нужно.

5. Честно говоря, сам с этим не разбирался. Но нам пока это тоже не нужно.

6. Ну и сама наша библиотека для организации HTTP-сервиса.

И еще немного кода...

using namespace std;
using namespace restbed;

map <string, string> srvArray;

Собственно, это у нас определение пространств имен (чтобы не писать перед каждой функцией и типом std::) и нашего "ассоциативного массива".

 

"ХЭНДЛЕРЫ"

void get_set_method_handler( const shared_ptr< Session > ss )
{
    const auto req = ss->get_request();
    auto data = req->get_path_parameter( "data" );
    srvArray[ data ] = req->get_path_parameter( "value" );
    ss->close( OK, "OK", { { "Content-Length", "2" } } );
}

void get_get_method_handler( const shared_ptr< Session > ss )
{
    const auto req = ss->get_request();
    auto data = req->get_path_parameter( "data" );
    if (!srvArray[ data ].empty()) {
        const string ret = srvArray[ data ];
        //cout << ret << endl;
        ss->close( OK, ret, { { "Content-Length", ::to_string( ret.size() ) } } );
    } else {
        //cout << "EMPTY" << endl;
        ss->close( OK, "EMPTY", { { "Content-Length", "5" } } );
    }
}

Здесь у нас два обработчика событий HTTP-сервиса, которые мы чуть ниже зарегистрируем.

Первый обработчик устанавливает ключ и значение по приехавшим параметрам. Второй обработчик возвращает установленный ранее параметр или строку "EMPTY", если такое значение мы еще не устанавливали.

Алгоритм тут достаточно прост:

1. Получаем из сессии (аргумент функции) текущий запрос (в принципе, все как в 1С).

2. Получаем из запроса именованный параметр(ы) (задается в шаблоне, увидите ниже).

3. Устанавливаем в ключ значение или извлекаем значение по ключу.

4. Возвращаем "ОК, значение или "ENPTY" (если значение с таким ключом еще не было установлено).

Ну и давайте перейдем к самому интересному...

 

ФУНКЦИЯ MAIN

int main ( const int carg, const char** arg)
{
    int port = 8080;
    if ( carg > 1 ) port = atoi( arg[1] );

    auto resource_set = make_shared< Resource >();
    resource_set->set_path( "/set/{data: .*}/{value: .*}" );
    resource_set->set_method_handler( "GET", get_set_method_handler );

    auto resource_get = make_shared< Resource >();
    resource_get->set_path( "/get/{data: .*}" );
    resource_get->set_method_handler( "GET", get_get_method_handler );

    auto settings = make_shared< Settings >();
    settings->set_port( port );
    settings->set_default_header( "Connection", "close" );

    Service service;
    service.publish( resource_set );
    service.publish( resource_get );

    service.start( settings );
}

Вот и вся программа на "супер-пупер-сложном" языке.

1. Указываем порт по умолчанию "8080".

2. Проверяем, есть ли параметры в командной строке.

3. Если параметры есть, то устанавливаем порт из первого (в действительности - второго).

4. Определяем первый наш HTTP-ресурс (SET - установка значения), как умный указатель с соответствующим типом значения.

5. Устанавливаем шаблон "/set/{data: .*}/{value: .*}". Я несколько минут потратил, пока до меня дошло, а Вы?

6. Определяем второй ресурс (GET - получение установленного ранее значения или "EMPTY").

7. Создаем настройку, передаем в нее порт, устанавливаем заголовки по умолчанию.

8. Создаем сервис и регистрируем там наши ресурсы.

9. Стартуем сервис с нашими настройками.

Ну и осталось извлечь пользу.

 

ДЕРНЕМ СЕРВИС ИЗ 1С

Ну тут тоже все просто, но чуть усложним и проведем нагрузочный тест.

 
 Код на 1C

 

Процедура ОтправитьВСервисНаСервере()
	СреднееВремя = 0;
	МаксВремя = 0;
	МинВремя = 100000000;
	ВсегоВремя = 0;

	Запрос = Новый Запрос(
		"ВЫБРАТЬ
		|	Номенклатура.Наименование КАК Наименование,
		|	Номенклатура.Код КАК Код
		|ИЗ
		|	Справочник.Номенклатура КАК Номенклатура");
	
	С = Новый HTTPСоединение("172.23.38.82",8080,,,,10);

	Т = Запрос.Выполнить().Выгрузить();
	Для Каждого Ст ИЗ Т Цикл 
		З = Новый HTTPЗапрос(СтрШаблон("/set/%1/%2",ст.код, КодироватьСтроку(СтрЗаменить(ст.Наименование,"/"," "),СпособКодированияСтроки.URLВКодировкеURL)));
		Время = ТекущаяУниверсальнаяДатаВМиллисекундах();
		О = С.Получить(З);
		ВремяТ = ТекущаяУниверсальнаяДатаВМиллисекундах() - Время;
		
		ВсегоВремя = ВсегоВремя + ВремяТ;
		МинВремя = Мин( МинВремя, ВремяТ);
		МаксВремя = Макс( МаксВремя, ВремяТ);
		
		Если НЕ О.КодСостояния = 200 Тогда 
			Сообщить( "Ошибка! " + О.ПолучитьТелоКакСтроку() );
		КонецЕсли;
	КонецЦикла;
	
	Сообщить(
		СтрШаблон( "Статистика SET:
		|Всего запросов: %4,
		|Минимальное время запроса: %1 мс,
		|Максимальное время запроса: %2 мс,
		|Среднее время запроса: %3 мс.", МинВремя, МаксВремя, Цел(ВсегоВремя / Т.Количество()), Т.Количество() )
		);
	
	
	Для Каждого Ст ИЗ Т Цикл 
		З = Новый HTTPЗапрос(СтрШаблон("/get/%1",ст.код));

		Время = ТекущаяУниверсальнаяДатаВМиллисекундах();
		О = С.Получить(З);
		ВремяТ = ТекущаяУниверсальнаяДатаВМиллисекундах() - Время;
		
		ВсегоВремя = ВсегоВремя + ВремяТ;
		МинВремя = Мин( МинВремя, ВремяТ);
		МаксВремя = Макс( МаксВремя, ВремяТ);

		//Сообщить( Ст.Код + "/" + О.ПолучитьТелоКакСтроку() );
	КонецЦикла;
	
	Сообщить(
		СтрШаблон( "Статистика GET:
		|Всего запросов: %4,
		|Минимальное время запроса: %1 мс,
		|Максимальное время запроса: %2 мс,
		|Среднее время запроса: %3 мс.", МинВремя, МаксВремя, Цел(ВсегоВремя / Т.Количество()), Т.Количество() )
		);
	
КонецПроцедуры

Ну суть кода проста - создаем соединение, дергаем SET с кодом товара в качестве ключа и закодированном наименовании номенклатуры в качестве значения. Дальше дергаем GET с кодом товара. В результат выводим ошибки и измеренное время доступа к сервису.

 
 Результат на большом и красивом компьютере

Ошибка! Argument is not a valid URI: http://localhost/set/000000047/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%903%20500%D0%BB%20%22Ballet%20Premier%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20161%%20CIE,%20%D0%90%20%D0%BA%D0%BB%D0%B0%D1%81%D1%81%20(%D1%80091745,%20%D0%BA398664)


Ошибка! Argument is not a valid URI: http://localhost/set/000000048/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%903%20500%D0%BB%20%22%D0%A1%D0%B2%D0%B5%D1%82%D0%BE%D0%BA%D0%BE%D0%BF%D0%B8%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20146%%20CIE,%20%D0%A1%20%D0%9A%D0%BB%D0%B0%D1%81%D1%81%20CIE%20(%D0%BA28993,%20%D1%80007221)


Ошибка! Argument is not a valid URI: http://localhost/set/000000049/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%904%20500%D0%BB%20%22Ballet%20Brilliant%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20168%%20CIE,%20%D0%90+%20%D0%9A%D0%BB%D0%B0%D1%81%D1%81%20(%D1%80212721)


Ошибка! Argument is not a valid URI: http://localhost/set/000000050/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%904%20500%D0%BB%20%22IQ%20AllRound%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20162%%20CIE(%D0%BA306383,%20%D1%80075193)


Ошибка! Argument is not a valid URI: http://localhost/set/000000051/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%904%20500%D0%BB%20%22%D0%A1%D0%B2%D0%B5%D1%82%D0%BE%D0%BA%D0%BE%D0%BF%D0%B8%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20146%%20CIE,%20%D0%A1%20%D0%9A%D0%BB%D0%B0%D1%81%D1%81%20(%D1%80000877,%20%D0%BA398657)


Ошибка! Argument is not a valid URI: http://localhost/set/000000052/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%904%20500%D0%BB%20%22%D0%A1%D0%BD%D0%B5%D0%B3%D1%83%D1%80%D0%BE%D1%87%D0%BA%D0%B0%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20146%%20CIE%20(%D0%BA306647)


Ошибка! Argument is not a valid URI: http://localhost/set/000000053/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%904%20500%D0%BB%20Ballet%20%22Classic%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20153%%20CIE,%20%D0%92%20%D0%BA%D0%BB%D0%B0%D1%81%D1%81%20(398639,%20398661)


Ошибка! Argument is not a valid URI: http://localhost/set/000000054/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%904%20500%D0%BB%20Ballet%20%22Premier%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20161%%20CIE,%20%D0%90%20%D0%BA%D0%BB%D0%B0%D1%81%D1%81%20(%D1%80066047,%20%D0%BA398663)


Ошибка! Argument is not a valid URI: http://localhost/set/000000055/%D0%91%D1%83%D0%BC%D0%B0%D0%B3%D0%B0%20%D0%BE%D1%84%D0%B8%D1%81%D0%BD%D0%B0%D1%8F%20%D1%84-%D1%82%20%D0%905%20500%D0%BB%20%22OfficeSpace%22%20%D0%B1%D0%B5%D0%BB%D0%B8%D0%B7%D0%BD%D0%B0%20149%%20CIE%201%2010%20(264198)


Ошибка! Argument is not a valid URI: http://localhost/set/000000403/%D0%9F%D0%BE%D0%B4%D1%81%D1%82%D0%B0%D0%B2%D0%BA%D0%B0%20%D0%90%D0%BA%D1%86%D0%B8%D1%8F%2030%%20205*175%20%D0%BC%D0%BC.%20(%D0%BA416133)


Статистика SET:
Всего запросов: 2 000,
Минимальное время запроса: 0 мс,
Максимальное время запроса: 34 мс,
Среднее время запроса: 9 мс.


Статистика GET:
Всего запросов: 2 000,
Минимальное время запроса: 0 мс,
Максимальное время запроса: 44 мс,
Среднее время запроса: 19 мс.

Сначала у меня для ряда позиций система возвратила ошибку, т.к. не смогла определить в запросе соответствие шаблону. Таких строк в моем справочнике не так и много - всего 10 из 2000. Над причиной мне было лень думать, но, например, символ "/" уже приведет к подобной ошибке.

Ну и скорость обращений с виртуалки на винде к хост-системе на убунту достаточно высокая - в среднем запрос выполняется за 9 мс для записи и 19 мс для чтения (не знаю, почему так). Максимальное время не превышает 50 мс. Давайте протестируем это на Rispberry PI 3 B.

sergey@sergey-X570-AORUS-ELITE:~$ ssh pi@172.23.38.105
pi@raspberrypi:~ $ g++ exmpl.cpp -lrestbed
pi@raspberrypi:~ $ ./a.out

Зашли на R PI, скомпилировали программку, запустили...

 
 Результат на меленьком, но гордом Rispberry PI 3 B

 Статистика SET:
Всего запросов: 2 000,
Минимальное время запроса: 0 мс,
Максимальное время запроса: 94 мс,
Среднее время запроса: 15 мс.


Статистика GET:
Всего запросов: 2 000,
Минимальное время запроса: 0 мс,
Максимальное время запроса: 125 мс,
Среднее время запроса: 31 мс.

С учетом того, что до Rispberry надо ехать через WIFI-роутер, то результат вполне себе приличный.

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

*** тестовая база 1С была развернута на бесплатной версии 1С для обучения программированию на виртаульной машине на базе VirtualBox 6.1.26, на которой была установлена винда 10 с опцией "у меня нет ключа". Подробнее тут: ТЫЛЫЩЬ!

REST. HTTP REST-API сервисы C++

См. также

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    15921    13    18    

13

Интеграция 1С — Битрикс24. Обмен задачами

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс24. Разработка имеет двухстороннюю синхронизацию 1С и Битрикс24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (8.3.18.1289). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    17872    6    15    

13

Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС

Обмен с ГосИС WEB-интеграция Платформа 1С v8.3 Управляемые формы 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

2400 руб.

28.04.2016    88910    163    216    

318

[Расширение] БОР-Навигатор.Культура

Зарплата Бюджетный учет WEB-интеграция Обмен с ГосИС Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бюджетный учет Платные (руб)

Расширение конфигурации, включающее в себя объекты, необходимые для подготовки и сдачи отчета "Штатная численность" системы "БОР-Навигатор.Культура" в программе "1С:Зарплата и кадры государственного учреждения", редакция 3.1.

8400 руб.

01.02.2019    25866    9    0    

7

Медиадисплей. Рекламный информационный монитор для покупателя.

Разработка внешних компонент POS терминал Рабочее место Розничная торговля Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Розничная и сетевая торговля (FMCG) Рестораны, кафе и фаст-фуд Реклама, PR и маркетинг Управленческий учет Платные (руб)

Монитор покупателя может отображать текущую покупку на кассовом месте, показывать видеорекламу, баннеры, во время простоя разворачивать рекламу на весь экран. Можно использовать в качестве графического меню-борда в кафе и видеовывески. Управление выводом на телевизор через hdmi-приставку на базе Windows или Android. В качестве устройства отображения можно использовать Android-планшеты, фоторамки с Android, монитор любого Windows-компьютера, доступного по сети. Настраивается ЛЮБОЙ ДИЗАЙН экрана!

16800 руб.

30.05.2017    52220    34    69    

43
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Nefilimus 75 01.11.21 15:14 Сейчас в теме
Название переменных божественны =)) Я что-то не понял в чём фишка... Это же обычный http запрос, не?
Сто27001; +1
2. starik-2005 3036 01.11.21 15:15 Сейчас в теме
(1)
Я что-то не понял в чём фишка.
Это веб-сервис на С++. Больше ничего необычного...
Nefilimus; +1
9. triviumfan 93 08.11.21 10:27 Сейчас в теме
(2) А можно узнать для чего? Если можно создать такой же сервис в самой 1с. Не понимаю сути этой ВК.
+
10. starik-2005 3036 08.11.21 13:26 Сейчас в теме
(9)
Не понимаю сути этой ВК.
Для обработки 10к запросов в секунду.
Nefilimus; +1
3. SGordon1 01.11.21 15:22 Сейчас в теме
А что нужно для https?
+
4. starik-2005 3036 01.11.21 15:25 Сейчас в теме
(3)
А что нужно для https?
Если перейдете по сцылке на гит, то найдете там в документации примеры, в которых есть и HTTPS.
https://github.com/Corvusoft/restbed/blob/master/documentation/example/HTTP­S_SERVICE.md
+
5. gybson 01.11.21 15:30 Сейчас в теме
Как механизм интеграции сгодится, но выгоды перед питоном не видно вот так сразу
+
6. starik-2005 3036 01.11.21 15:32 Сейчас в теме
(5)
но выгоды перед питоном не видно вот так сразу
Выгоды перед питоном не видно до тех пор, пока не придется что-то простое, но большое, обрабатывать. С++ на несколько порядков быстрее питона может в ряде случаев работать, при этом требует сильно меньше ресурсов. При том современный С++ - это уже не сильно сложнее питона...
cobroid; davdykin; +2
7. gybson 01.11.21 16:50 Сейчас в теме
(6)может то оно может, только программист нужен опытный. Современный С++ достаточно сложен, чтобы утонуть в утечках памяти, исключениях и прочем. Масштабирование сервиса под вопросом. У питона то под капотом такой же С++ код, только с ним работать проще.
+
8. starik-2005 3036 01.11.21 17:00 Сейчас в теме
(7)
чтобы утонуть в утечках памяти, исключениях и прочем
C STL и умными указателями \то будет сложно сделать. Исключения в 99% случаев от того, что переменной не выделена память, но сейчас это статическое выделение или с помощью объектов STL, так что утечки тоже давно уже канули в лету (если, конечно, не программировть на С варианта 90-х).
+
11. user1886088 18.12.22 19:05 Сейчас в теме
А чего не GO? Там реализовать http сервер на порядок проще с со скоростью у него тоже все хорошо.
+
12. starik-2005 3036 30.12.22 14:35 Сейчас в теме
(11)
Там реализовать http сервер на порядок проще с со скоростью у него тоже все хорошо
Приведите пример этого "проще".
+
13. ivan1703 78 20.04.23 21:20 Сейчас в теме
еще проще )))

#include "httplib.h"

int main()
{
    httplib::Server listener;
    listener.Get("/", [](const Request&, Response& res){
        res.set_content("Hello it's c++ !!!", "application / json; charset = utf-8");
    });
    listener.listen("0.0.0.0", 80);
}
Показать
+
14. starik-2005 3036 20.04.23 21:40 Сейчас в теме
(13)
httplib
Тоже неплохо.
+
Оставьте свое сообщение