Реализация сущности Server в примере echo
В коде сущности Server
используются транспортные типы и методы, которые будут сгенерированы во время сборки решения компилятором NK на основе EDL-описания сущности Server
.
Однако чтобы получить необходимые для реализации сущности типы и сигнатуры методов, вы можете воспользоваться компилятором NK непосредственно после создания EDL-описания сущности, CDL-описаний компонентов и IDL-описаний используемых интерфейсов взаимодействия. В результате необходимые типы и сигнатуры методов будут объявлены в сгенерированных файлах *.h
.
В реализации сущности server
необходимо:
- Реализовать метод
Ping()
.Сигнатура реализации метода
Ping()
должна в точности совпадать с сигнатурой интерфейсного методаPing_Ping()
, который объявлен в файле Ping.idl.h. - Получить серверный IPC-дескриптор соединения (канала), используя функцию локатора сервисов
ServiceLocatorRegister()
.На вход нужно передать имя IPC-соединения
server_connection
, заданное ранее в файле init.yaml. - Инициализировать транспорт
NkKosTransport
, передав полученный IPC-дескриптор в функциюNkKosTransport_Init()
. - Подготовить структуры запроса и ответа.
- Инициализировать dispatch-метод (диспетчер) компонента
Ping
, используя функциюPing_component_init()
. - Инициализировать dispatch-метод (диспетчер) сущности
Server
, используя функциюServer_entity_init()
. - Получить запрос, вызвав
nk_transport_recv()
. - Обработать полученный запрос, вызвав диспетчер
Server_entity_dispatch()
.Диспетчер вызовет необходимую реализацию метода на основе полученного от клиента идентификатора интерфейса (
RIID
). - Отправить ответ сущности
Client
, вызвавnk_transport_reply()
.
server.c
/* Файлы, необходимые для инициализации транспорта. */
/* Описания сущности-сервера на языке EDL. */
/* Тип объекта реализующего интерфейс. */
typedef struct IPingImpl {
struct echo_Ping base; // базовый интерфейс объекта
int step; // дополнительные параметры
} IPingImpl;
/* Реализация метода Ping. */
static nk_err_t Ping_impl(struct echo_Ping *self,
const echo_Ping_req *req,
const struct nk_arena* req_arena,
echo_Ping_res* res,
struct nk_arena* res_arena)
{
IPingImpl *impl = (IPingImpl *)self;
/* Значение value, пришедшее в запросе от клиента, инкрементируем на
* величину шага step и помещаем в аргумент result, который будет
* отправлен клиенту в составе ответа от сервера. */
res->Ping.result = req->Ping.value + impl->step;
return NK_EOK;
}
/* Конструктор объекта IPing.
* step - шаг, то есть число, на которое будет увеличиваться входящее значение. */
static struct echo_Ping *CreateIPingImpl(int step)
{
/* Таблица реализаций методов интерфейса IPing. */
static const struct echo_Ping_ops ops = {
.Ping = Ping_impl
};
/* Объект, реализующий интерфейс. */
static struct IPingImpl impl = {
.base = {&ops}
};
impl.step = step;
return &impl.base;
}
/* Точка входа в сервер. */
int main(void)
{
NkKosTransport transport;
ServiceId iid;
/* Получаем серверный IPC-дескриптор соединения "server_connection". */
Handle handle = ServiceLocatorRegister("server_connection", NULL, 0, &iid);
assert(handle != INVALID_HANDLE);
/* Инициализируем транспорт до клиента. */
NkKosTransport_Init(&transport, handle, NK_NULL, 0);
/* Подготавливаем структуры запроса к сущности server: фиксированную
* часть и арену. Поскольку ни у одного из методов сущности server нет
* аргументов типа sequence, используются только фиксированные части
* запроса и ответа. Арены фактически не используются. Однако в серверные
* методы транспорта (nk_transport_recv, nk_transport_reply) и
* dispatch-метод server_entity_dispatch необходимо передать валидные
* арены запроса и ответа. */
echo_Server_entity_req req;
char req_buffer[echo_Server_entity_req_arena_size];
struct nk_arena req_arena = NK_ARENA_INITIALIZER(req_buffer, req_buffer + sizeof(req_buffer));
/* Подготавливаем структуры ответа: фиксированную часть и арену. */
echo_Server_entity_res res;
char res_buffer[echo_Server_entity_res_arena_size];
struct nk_arena res_arena = NK_ARENA_INITIALIZER(res_buffer, res_buffer + sizeof(res_buffer));
/* Инициализируем диспетчер компонента ping. 3 – величина шага,
* то есть число, на которое будет увеличиваться входящее значение. */
echo_Ping_component component;
echo_Ping_component_init(&component, CreateIPingImpl(3));
/* Инициализируем диспетчер сущности server. */
echo_Server_entity entity;
echo_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, "nk_transport_recv error\n");
} else {
/* Обрабатываем полученный запрос, вызывая реализацию Ping_impl
* запрошенного интерфейсного метода Ping. */
echo_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, "nk_transport_reply error\n");
}
}
while (true);
return EXIT_SUCCESS;
}