Реализация сущности Server в примере ping
Инициализация транспорта до клиента, подготовка структур запроса и ответа, а также назначение файла Server.edl.h
рассматриваются более подробно в комментариях к файлу server.c в примере echo.
server.c
/* Файлы, необходимые для инициализации транспорта. */
/* Описания сущности-сервера на языках EDL, CDL, IDL. */
static const char *Tag = "[Server]";
/* Тип объекта реализующего интерфейс. */
typedef struct ObjectImpl
{
struct Connection base; /* базовый интерфейс объекта */
int step; /* дополнительные параметры */
} ObjectImpl;
/* Реализация метода Ping. */
static nk_err_t Ping_impl(
struct Connection *self,
const struct Connection_Ping_req *req,
const struct nk_arena *req_arena,
struct Connection_Ping_res *res,
struct nk_arena *res_arena)
{
ObjectImpl *impl = (ObjectImpl *)self;
/**
* Значение value, пришедшее в запросе от клиента, инкрементируем на
* величину шага step и помещаем в аргумент result, который будет
* отправлен клиенту в составе ответа от сервера.
*/
res->result = req->value + (unsigned int)impl->step;
return NK_EOK;
}
/* Реализация метода Pong. */
static nk_err_t Pong_impl(
struct Connection *self,
const struct Connection_Pong_req *req,
const struct nk_arena *req_arena,
struct Connection_Pong_res *res,
struct nk_arena *res_arena)
{
ObjectImpl *impl = (ObjectImpl *)self;
/**
* Значение value, пришедшее в запросе от клиента, инкрементируем на
* величину шага step и помещаем в аргумент result, который будет
* отправлен клиенту в составе ответа от сервера.
*/
res->result = req->value + (unsigned int)impl->step;
return NK_EOK;
}
/**
* Конструктор объекта Ping.
* step - шаг, то есть число, на которое будет увеличиваться входящее значение.
*/
static struct Connection *CreateObjectImpl(int step)
{
/* Таблица реализаций методов интерфейса Connection. */
static const struct Connection_ops ops = {.Ping = Ping_impl, .Pong = Pong_impl};
/* Объект, реализующий интерфейс. */
static struct ObjectImpl impl = {.base = {&ops}};
impl.step = step;
return &impl.base;
}
/* Точка входа в сервер. */
int main(void)
{
NkKosTransport transport;
ServiceId iid;
/* Регистрируем соединение и получаем дескриптор для него. */
Handle handle = ServiceLocatorRegister("server_connection", NULL, 0, &iid);
if (INVALID_HANDLE == handle)
{
fprintf(stderr, "%s Failed to register service locator\n", Tag);
return EXIT_FAILURE;
}
/* Инициализируем транспорт до клиента. */
NkKosTransport_Init(&transport, handle, NK_NULL, 0);
/* Подготавливаем структуры запроса: фиксированную часть и арену. */
union Server_entity_req req;
char req_buffer[Server_entity_req_arena_size];
struct nk_arena req_arena = NK_ARENA_INITIALIZER(req_buffer, req_buffer + sizeof(req_buffer));
/* Подготавливаем структуры ответа: фиксированную часть и арену. */
union Server_entity_res res;
char res_buffer[Server_entity_res_arena_size];
struct nk_arena res_arena = NK_ARENA_INITIALIZER(res_buffer, res_buffer + sizeof(res_buffer));
/**
* Инициализируем диспетчер компонента Control. INCREMENT_STEP – значение "шага",
* которое будет прибавляться к входному аргументу value.
**/
struct Control_component component;
Control_component_init(&component, CreateObjectImpl(INCREMENT_STEP));
/* Инициализируем диспетчер сущности Server. */
struct Server_entity entity;
Server_entity_init(&entity, &component);
fprintf(stderr, "Hello I'm server\n");
/* Реализация цикла обработки запросов. */
do
{
/* Сбрасываем буферы с запросом и ответом. */
nk_req_reset(&req);
nk_arena_reset(&req_arena);
nk_arena_reset(&res_arena);
/* Ожидаем запрос от клиента. */
if (nk_transport_recv(&transport.base, &req.base_, &req_arena) != NK_EOK)
{
fprintf(stderr, "%s nk_transport_recv error\n", Tag);
}
else
{
/**
* Обрабатываем полученный запрос, вызывая реализацию connectionimpl
* запрошенного интерфейсного метода Ping.
*/
Server_entity_dispatch(&entity, &req.base_, &req_arena, &res.base_, &res_arena);
}
/* Отправляем ответ. */
if (nk_transport_reply(&transport.base, &res.base_, &res_arena) != NK_EOK)
{
fprintf(stderr, "%s nk_transport_reply error\n", Tag);
}
} while (true);
return EXIT_SUCCESS;
}