һ��С�ɡ���Ч���ͺĵ�C����ջ��RESTfulӦ�÷���ƽ̨(restserver)
1. Введение
2. Цель
3. «Hello world»
4. Структура проекта
4.1. Компоненты структуры
4.2. Логическая структура
5. Сборка и тестирование
5.1. Этапы сборки и тестирования
5.1.1. Сборка и тестирование приложения
5.1.1.1. fasterjson
5.1.1.2. tcpdaemon
5.1.1.3. fasterhttp
5.1.2. Сборка и тестирование restserver
5.1.3. Сборка и тестирование примера использования restserver
6. Использование
6.1. Использование и обслуживание
6.2. Одноразовое использование шаблона
6.3. Самостоятельная сборка и использование restserver
7. Тестирование
7.1. Модульное тестирование
7.2. Интеграционное тестирование
8. RESTful API
8.1. Реализация API
8.2. Библиотека функций
8.2.1. Основные функции
8.2.1.1. STRNCMPSTRN
8.2.1.2. STRNCMPSTR
8.2.1.3. STRNCMPRSTR
8.2.1.4. HTTP_NEWLINE
8.2.1.5. HTML_NEWLINE
8.2.1.6. HTML_RETURN_NEWLINE
8.2.1.7. BUFNPRINTF
8.2.1.8. BUFPRINTF
8.2.1.9. BUFNSTRCAT
8.2.1.10. BUFSTRCAT
8.3. Функции инициализации, вызова и очистки rest-приложения
8.3.1. Функции работы с rest-приложением
8.3.1.1. funcInitRestApplication
8.3.1.2. funcCallRestApplication
8.3.1.3. funcCleanRestApplication
8.4. API функций
8.4.1. Получение информации о запросе
8.4.1.1. RSAPIGetHttpMethodPtr
8.4.1.2. RSAPIGetHttpUriPtr
8.4.1.3. RSAPIGetHttpUriPathsCount
8.4.1.4. RSAPIGetHttpUriPathPtr
8.4.1.5. RSAPIGetHttpUriQueriesCount
8.4.1.6. RSAPIGetHttpUriQueryKeyPtr
8.4.1.7. RSAPIGetHttpUriQueryValuePtr
8.4.1.8. RSAPIGetHttpRequestBodyPtr **4.2. Архитектура**
На рисунке представлена архитектура системы, где restserver взаимодействует с tcpdaemon через TCP-соединение.
TCP-демон (tcpdaemon) обрабатывает входящие TCP-соединения и передаёт запросы в основной процесс (tcpmain).
Основной процесс (tcpmain) получает HTTP-запросы от TCP-демона, обрабатывает их и возвращает ответ.
Процесс обработки HTTP-запроса включает следующие шаги:
RESTful-приложение работает следующим образом:
RESTful API диспетчеризует запросы к контроллерам RESTful service controler.
RESTful service application — это RESTful-приложение, которое предоставляет RESTful API для управления ресурсами.
Клонируйте репозиторий fasterjson с GitHub или Gitee. Перейдите в каталог src и выполните команду make -f makefile.Linux install. Библиотеки будут установлены в каталоги $HOME/include/fasterjson/ и $HOME/lib/libfasterjson.so.
Клонируйте репозиторий tcpdaemon с GitHub или Gitee. Перейдите в каталог src и выполните команду make -f makefile.Linux install. Библиотека будет установлена в каталог $HOME/lib/libtcpdaemon.a.
Клонируйте репозиторий fasterhttp с GitHub или Gitee. Перейдите в каталог src и выполните команду make -f makefile.Linux install. Библиотека будет установлена в каталог $HOME/lib/libfasterhttp.so.
Клонируйте репозиторий restserver с GitHub или Gitee. Перейдите в каталог src и выполните команду make -f makefile.Linux install. Программа будет установлена в каталоги $HOME/bin/restserver, $HOME/include/restserver/ и $HOME/lib/librestserver_api.so.
Перейдите в каталог example и выполните команду make -f makefile.Linux. ``` funcRestServiceEntry GET_hello; int GET_hello( struct RestServerContext *ctx ) { char response[1024] ; int response_len ;
int nret = 0 ;
/* Инициализация */
memset( response , 0x00 , sizeof(response) );
response_len = 0 ;
/* Формирование ответа */
response_len = snprintf( response , sizeof(response) , "Hello restserver\n" ) ;
/* Форматирование HTTP-ответа */
nret = RSAPIFormatHttpResponse( ctx , response , response_len , NULL ) ;
if( nret )
return nret;
return 0;
}
*Здесь представлен перевод фрагмента исходного текста на русский язык.*
**Обратите внимание, что в исходном тексте присутствуют фрагменты кода и специальные символы, которые не были переведены.** **Текст запроса написан на языке C.**
**Перевод текста:**
char buf1[...] ; char buf2[...] ; ... if( STRNCMPSTR( buf1 , strlen(buf1) , == , buf2 ) ) { ... }
#### 8.2.1.3. STRNCMPRSTR
| Определение | #define STRNCMPRSTR(\_str1\_,\_str1\_len\_,\_cmp\_,\_const_str2\_) STRNCMPSTRN( (\_str1\_) , (\_str1\_len\_) , \_cmp\_ , \(_literal\_str2\_) , (sizeof(\_literal\_str2\)-1) ) |
| --- | --- |
| Описание | Функция сравнивает первые _str1_len_ символов строки _str1_ с подстрокой _literal_str2_ и возвращает результат сравнения. |
| Пример | _str1_: «привет»; _str1_len_: 6; _cmp_: ==; _literal_str2_: «мир» |
| Таблица значений | 0: «привет»; 1: «приве»; С: «вет» |
char buf1[...] ; ... if( STRNCMPRSTR( buf1 , strlen(buf1) , == , "hello" ) ) { ... }
#### 8.2.1.4. HTTP_NEWLINE
| Определение | #define HTTP_NEWLINE "\r\n" |
| Перевод | #define HTTP_NEWLINE — «\r\n» |
#### 8.2.1.5. HTML_NEWLINE
| Определение | #define HTML_NEWLINE "<br />" |
| Перевод | #define HTML_NEWLINE — "<br />" |
#### 8.2.1.6. HTML_RETURN_NEWLINE
| Определение | #define HTML_RETURN_NEWLINE "<p />" |
| Перевод | #define HTML_RETURN_NEWLINE — "<p />" |
#### 8.2.1.7. BUFNPRINTF
| Определение | #define BUFNPRINTF(\_buf\_base\_,\_buf\_size\_,\_str\_len\_,\_format\_,...) ... |
| Перевод | #define BUFNPRINTF — ... |
| Описание | Записывает форматированную строку в буфер. |
| Параметры | _buf_base_ — адрес буфера; _buf_size_ — размер буфера; _str_len_ — длина строки; _format_ — строка формата; ... — аргументы строки формата. |
| Результат | Нет. |
char buf[...] ; int buf_len ; int count ; ... BUFNPRINTF( buf , sizeof(buf) , buf_len , "count[%d]" , count )
*Примечание: не указано, что происходит при превышении размера буфера.*
#### 8.2.1.8. BUFPRINTF
| Определение | #define BUFPRINTF(\_buf\_base\_,\_str\_len\_,\_format\_,...) BUFNPRINTF(\_buf\_base\_,sizeof(\_buf\_base\_),\_str\_len\_,\_format\_,\_\_VA_ARGS\_\_) |
| Перевод | #define BUFPRINTF — BUFNPRINTF |
| Описание | То же, что и BUFNPRINTF. |
char buf[...] ; int buf_len ; int count ; ... BUFPRINTF( buf , buf_len , "count[%d]" , count )
*Примечание: не указано, что происходит при превышении размера буфера.*
#### 8.2.1.9. BUFNSTRCAT
| Определение | #define BUFNSTRCAT(_buf_base_,_buf_size_,_str_len_,_cat_str_) ... |
| Перевод | #define BUFNSTRCAT — ... |
| Описание | Добавляет строку _cat_str_ в конец строки, хранящейся по адресу _buf_base_. |
| Параметры | _buf_base_ — адрес строки; _buf_size_ — размер строки; _str_len_ — текущая длина строки; _cat_str_ — добавляемая строка. |
| Результат | Нет. |
char buf[...] ; int buf_len ; ... BUFNSTRCAT( buf , sizeof(buf) , buf_len , "ok" )
*Примечание: не указано, что произойдёт при превышении размера буфера после добавления строки.*
#### 8.2.1.10. BUFSTRCAT
| Определение | #define BUFSTRCAT(\_buf\_base\_,\_str\_len\_,\_cat\_str_) BUFNSTRCAT(\_buf\_base\_,sizeof(\_buf\_base\_),\_str\_len\_,\_cat\_str_) |
| Перевод | #define BUFSTRCAT — BUFNSTRCAT |
| Описание | То же, что и BUFNSTRCAT. |
char buf[...] ; int buf_len ; ... BUFSTRCAT( buf , buf_len , "ok" )
*Примечание: не указано, что произойдёт при превышении размера буфера после добавления строки.*
## 8.3. Функции
### 8.3.1. Инициализация REST-приложения
#### 8.3.1.1. funcInitRestApplication
| Описание функции | typedef int funcInitRestApplication( struct RestServerContext *ctx ); |
| Перевод описания функции | funcInitRestApplication — функция типа int, которая принимает указатель на структуру RestServerContext и возвращает int. |
| Описание параметра | struct RestServerContext *ctx — указатель на контекст REST-сервера. |
| Возвращаемое значение | Нет. |
| Возможные значения | 0 — ошибка; ненулевое значение — успешное выполнение. |
#### 8.3.1.2. funcCallRestApplication
| Описание функции | typedef int funcCallRestApplication( struct RestServerContext *ctx ); |
| Перевод описания функции | funcCallRestApplication — функция типа int, которая принимает указатель на структуру RestServerContext и возвращает int. |
| Описание параметра | struct RestServerContext *ctx — указатель на контекст REST-сервера. |
| Возвращаемое значение | Нет. |
| Возможные значения | 0 — ошибка; ненулевое значение — успешное выполнение. |
#### 8.3.1.3. funcCleanRestApplication
| Описание функции | typedef int funcCleanRestApplication( struct RestServerContext *ctx ); |
| Перевод описания функции | funcCleanRestApplication — функция типа int, которая принимает указатель на структуру RestServerContext и возвращает int. |
| Описание параметра | struct RestServerContext *ctx — указатель на контекст REST-сервера. |
| Возвращаемое значение | Нет. |
| Возможные значения | 0 — ошибка; ненулевое значение — успешное выполнение. **8.4.1. RESTful API**
#### 8.4.1.1. RSAPIGetHttpMethodPtr
| Параметр | Описание |
| --- | --- |
| char *RSAPIGetHttpMethodPtr(struct RestServerContext *ctx, int *p_method_len) | Получает указатель на метод HTTP. |
| struct RestServerContext *ctx | Контекст сервера. |
| int *p_method_len | Указатель на длину метода HTTP. |
| char * | Метод HTTP. |
#### 8.4.1.2. RSAPIGetHttpUriPtr
| Параметр | Описание |
| ------- | -------- |
| char *RSAPIGetHttpUriPtr(struct RestServerContext *ctx, int *p_uri_len) | Получает указатель на URI HTTP. |
| struct RestServerContext *ctx | Контекст сервера. |
| int *p_uri_len | Указатель на длину URI HTTP. |
| char * | URI HTTP. |
#### 8.4.1.3. RSAPIGetHttpRequestBodyPtr
| Параметр | Описание |
| --------- | ----------- |
| int RSAPIGetHttpRequestBodyPtr(struct RestServerContext *ctx, int *p_body_len) | Получает длину тела запроса HTTP. |
| struct RestServerContext *ctx | Контекст сервера. |
| int *p_body_len | Указатель на длину тела запроса HTTP. |
| char * | Тело запроса HTTP. |
**8.4.2. Реализация RESTful API**
#### 8.4.2.1. RSAPIFormatHttpResponse
| Параметр | Описание |
| ------ | ------- |
| int RSAPIFormatHttpResponse(struct RestServerContext *ctx, char *http_response_body, int http_response_body_len, char *http_header_format, ...) | Форматирует ответ HTTP. |
| struct RestServerContext *ctx | Контекст сервера. |
| char *http_response_body | Тело ответа HTTP. |
| int http_response_body_len | Длина тела ответа HTTP. |
| char *http_header_format | Формат заголовка HTTP. |
**8.4.3. Создание RESTful сервиса**
#### 8.4.3.1. RSAPICreateRestServiceControler
| Параметр | Описание |
| ----- | ------- |
| struct RestServiceControler *RSAPICreateRestServiceController(struct RestServiceConfig *config_array) | Создаёт контроллер RESTful сервиса. |
| struct RestServiceConfig *config_array | Массив конфигураций сервиса. **8.4.3.2. RSAPIDispatchRestServiceControler**
| Наименование | Описание |
| --- | --- |
| int RSAPIDispatchRestServiceControler(struct RestServiceControler *ctl, struct RestServerContext *ctx) | RESTful-контроллер для обработки запросов к серверу. |
| Описание | Контроллер принимает запросы от сервера и обрабатывает их в соответствии с RESTful API. |
| Параметры | * ctl — указатель на структуру RestServiceControler, которая содержит информацию о контроллере;* ctx — указатель на контекст сервера, который содержит информацию о запросе. |
| Возвращаемое значение | 0 — успешное выполнение функции; любое другое значение — ошибка. |
**8.4.3.3. RSAPIDestroyRestServiceControler**
| Наименование | Описание |
| ------ | ------- |
| void RSAPIDestroyRestServiceControler(struct RestServiceControler *ctl) | Функция для освобождения ресурсов, выделенных под контроллер. |
| Описание | Освобождает ресурсы, выделенные под контроллер, и делает его недоступным для использования. |
| Параметр | ctl — указатель на контроллер, который нужно освободить. |
| Возвращаемого значения нет | |
**8.4.4. Функции для работы с контекстом сервера**
**8.4.4.1. RSAPIGetHttpEnv**
| Наименование | Описание |
| -------- | --------- |
| struct HttpEnv *RSAPIGetHttpEnv(struct RestServerContext *ctx) | Функция возвращает указатель на окружение HTTP-запроса. |
| Описание | Возвращает указатель на структуру HttpEnv, которая содержит информацию об окружении HTTP-запроса, включая метод запроса, URI и параметры запроса. |
| Параметр | ctx — указатель на контекст сервера. |
| Возвращаемое значение | Указатель на структуру HttpEnv. |
**8.4.4.2. RSAPISetUserData**
| Наименование | Описание |
| ----------- | ------------ |
| void RSAPISetUserData(struct RestServerContext *ctx, void *user_data) | Устанавливает пользовательские данные в контексте сервера. |
| Описание | Записывает указатель на пользовательские данные в контекст сервера. Эти данные могут быть использованы для хранения информации о текущем пользователе или состоянии приложения. |
| Параметры | ctx — контекст сервера; user_data — указатель на пользовательские данные. |
| Возвращаемого значения нет | |
**8.4.4.3. RSAPIGetUserData**
| Наименование | Описание |
| ------------- | -------------- |
| void *RSAPIGetUserData(struct RestServerContext *ctx) | Получает указатель на пользовательские данные из контекста сервера. |
| Описание | Извлекает указатель на пользовательские данные, которые были установлены ранее с помощью функции RSAPISetUserData. |
| Параметр | ctx — контекст сервера. |
| Возвращаемое значение | Указатель на пользовательские данные или NULL, если данные не были установлены. | **Перевод текста на русский язык:**
RSAPIFormatHttpResponse(ctx, response, response_len, NULL);
if (nret)
return nret;
return 0;
}
/* RESTful��������� ���������� */
static struct RestServiceConfig g_rest_services_config[] = {
{ "GET", "/rsapi", GET_hello },
{ "", "", NULL }
};
funcInitRestApplication InitRestApplication;
int InitRestApplication(struct RestServerContext *ctx)
{
struct RestServiceControler *ctl = NULL;
/* ����RESTful��������� */
ctl = RSAPICreateRestServiceControler(g_rest_services_config);
if (ctl == NULL)
return RESTSERVER_FATAL_CREATE_RESTSERVICECONTROLER;
/* ����RESTful�����������restserverƽ̨�����Ļ����� */
RSAPISetUserData(ctx, ctl);
return 0;
}
funcCallRestApplication CallRestApplication;
int CallRestApplication(struct RestServerContext *ctx)
{
struct RestServiceControler *ctl = NULL;
int nret = 0;
/* ��restserverƽ̨�����Ļ�����ȡ��RESTful��������� */
ctl = RSAPIGetUserData(ctx);
if (ctl == NULL)
return RESTSERVER_FATAL_GET_RESTSERVICECONTROLER;
/* ��RESTful������������ɷ�������� */
nret = RSAPIDispatchRestServiceControler(ctl, ctx);
if (nret)
return nret;
return 0;
}
funcCleanRestApplication CleanRestApplication;
int CleanRestApplication(struct RestServerContext *ctx)
{
struct RestServiceControler *ctl = NULL;
/* ��restserverƽ̨�����Ļ�����ȡ��RESTful��������� */
ctl = RSAPIGetUserData(ctx);
/* ����RESTful��������� */
RSAPIDestroyRestServiceControler(ctl);
return 0;
}
# 9. ����ѹ��
restserver��������أ���Tomcat�������ܱ�����
Ӳ������ >>>
CPU: Intel Core i5-7500 3.40GHz 3.40GHz
�ڴ�: 1 GB
Ӳ��: ST1000DM010
�������� >>>
����ϵͳ���ⲿ��Windows 10(64bits)��װ��Vmware�����������Red Hat Enterprise Linux Server release 7.4 (Maipo)
JDK: openjdk version "1.8.0_131"
restserver: restserver v0.8.0
Tomcat: apache-tomcat-10.0.0-M1
�������� >>>
�ֱ�restserver��Tomcat�����ܲ���Ӧ�ã�restserverӦ��Դ����`benchmark/restserver/press/`��TomcatӦ��Դ����`benchmark/Tomcat/TestAgainstRestServer/`����������HTTP�غɲ�ࡣ
����100���ܹ�10���HTTP�����Ƚ�����ʮ��Ԥ�ȣ�Ȼ������ʮ��ѹ�⡣
ȡrestserver��ʽ��һ�����
$ ab -c 100 -n 100000 -k "http://localhost:7911/TestAgainstRestServer/hello" This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient) Completed 10000 requests Completed 20000 requests Completed 30000 requests Completed 40000 requests Completed 50000 requests Completed 60000 requests Completed 70000 requests Completed 80000 requests Completed 90000 requests Completed 100000 requests Finished 100000 requests
Server Software:
Server Hostname: localhost
Server Port: 7911
Document Path: /TestAgainstRestServer/hello Document Length: 17 bytes
Concurrency Level: 100 Time taken for tests: 0.647 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Keep-Alive requests: 100000 Total transferred: 19300000 bytes HTML transferred: 1700000 bytes Requests per second: 154499.81 [#/sec] (mean) Time per request: 0.647 [ms] (mean) Time per request: 0.006 [ms] (mean, across all concurrent requests) Transfer rate: 29119.59 [Kbytes/sec] received
Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 3 Processing: 0 1 0.6 1 12 Waiting: 0 1 0.6 1 12 Total: 0 1 0.6 1 12
Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 1 98% 1 99% 2 100% 12 (longest request)
��ȡTomcat��һ�����
$ ab -c 100 -n 100000 -k "http://192.168.6.74:8080/TestAgainstRestServer/hello" This is ApacheBench, Version 2.3 <$Revision:
Примечание: в тексте запроса присутствуют фрагменты кода, которые не удалось перевести. Это связано с тем, что некоторые фрагменты написаны на языке программирования, который не поддерживается переводчиком. Бенчмаркинг 192.168.6.74 (будьте терпеливы)
Завершено 10000 запросов Завершено 20000 запросов Завершено 30000 запросов Завершённо 40000 запросов Завершено 50000 запросов Завершено 60000 запросов Завершено 70000 запросов Завершено 80000 запросов Завершено 90000 запросов Завершено 100000 запросов Закончено 100000 запросов.
Программное обеспечение сервера:
Путь к документу: /TestAgainstRestServer/hello Длина документа: 17 байт
Уровень параллелизма: 100 Время, затраченное на тесты: 1,765 секунды Общее количество выполненных запросов: 100 000 Неудачные запросы: 0 Ошибки записи: 0 Запросы Keep-Alive: 99 048 Общий объём переданных данных: 17 772 392 байта Переданные данные HTML: 1 700 000 байт Количество запросов в секунду: 56 662,49 [#/сек] (среднее значение) Время на запрос: 1,765 [мс] (среднее значение) Время на запрос: 0,018 [мс] (среднее значение для всех одновременных запросов) Скорость передачи: 9 834,26 [Кбайт/сек] получено
Время соединения (мс): * мин: 0 * среднее значение [+/- sd]: 0 1,4 * медиана: 0 * макс: 3
Процент запросов, обработанных за определённое время (мс): * 50%: 1 * 66%: 2 * 75%: 2 * 80%: 2 * 90%: 3 * 95%: 4 * 98%: 5 * 99%: 5 * 100%: 37 (самый длинный запрос)
�ܴ����ֽ���restserver��Tomcat��һ�㡣
������ÿ���������������ݣ�
| ��� | restserverÿ������������ | Tomcatÿ������������ |
| --- | --- | --- |
| 1 | 154499 | 56662 |
| 2 | 171290 | 56355 |
| 3 | 151884 | 58522 |
| 4 | 159883 | 55684 |
| 5 | 157284 | 57360 |
| 6 | 153655 | 56929 |
| 7 | 155253 | 56602 |
| 8 | 157085 | 55785 |
| 9 | 153904 | 57366 |
| 10 | 154064 | 55273 |
����ͼ�ҾͲ����ˣ������ԣ�restserverÿ�����������´ﵽTomcat��������
����������ƽ���ӳ����ݣ�
| ��� | restserver����ƽ���ӳ� | Tomcat����ƽ���ӳ� |
| --- | --- | --- |
| 1 | 0.006 | 0.018 |
| 2 | 0.006 | 0.018 |
| 3 | 0.007 | 0.017 |
| 4 | 0.006 | 0.018 |
| 5 | 0.006 | 0.017 |
| 6 | 0.007 | 0.018 |
| 7 | 0.006 | 0.018 |
| 8 | 0.006 | 0.018 |
| 9 | 0.006 | 0.017 |
| 10 | 0.006 | 0.018 |
����ͼҲ�����ˣ������ԣ�restserver����ƽ���ӳ�ֻ��Tomcat��1/3��
���ۣ�restserver����������ȫ��ѹTomcat��
# 10. ���
restserver��һ��С�ɡ���Ч���ͺĵ�C����ջ��RESTfulӦ�÷���ƽ̨��
��ӭʹ��restserver�������ʹ��������������������ң�лл ^_^
Դ���йܵ�ַ : [��Դ�й�](https://gitee.com/calvinwilliams/restserver)��[github](https://github.com/calvinwilliams/restserver)
�������ߣ�����������C������JAVA��д��С������Խ�����ݵ���־�⡢HTTP����������־�ɼ����ȣ�����ƽ̨/�м���ȣ��ֲ�ʽϵͳʵ���ߣ���������ר���ߣ�Ŀǰ��ij�����и�������ܹ���
ͨ�����������ϵ�� : [����](mailto:calvinwilliams@163.com)��[Gmail](mailto:calvinwilliams.c@gmail.com)
*Примечание: часть текста не удалось перевести из-за отсутствия контекста.*
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )