выполнит, скажем, чтение, что, по сути, тоже является отосланным сообщением. Поэтому при получении сообщений необходимо производить их «фильтрацию»:

if (MsgBuf.hdr_type >= _IO_BASE && Buffer.hdr.type <= _IO_MAX) {

 MsgError(rcvid, ENOSYS);

 continue;

}

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

С учетом этих деталей и организован нижеописанный сервер.

Код процесса-сервера, использующего службу глобальных имен

#include <stdio.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/dispatch h>

/* На сервер могут приходить и импульсы. Как минимум. */

typedef struct _pulse msg_header_t;

/* Структура сообщения состоит из заголовка и буфера наших данных */

typedef struct _MsgBuf {

 msg_header_t hdr;

 char* Buffer;

} MsgBuf_t;

int main() {

 name_attach_t* NameServer;

 MsgBuf_t MsgBuf;

 int rcvid;

 char BufReply[100];

 int flagWork = 1;

 /* Создаем глобальное имя /dev/name/global/MyService */

 if (!(NameServer = name_attach(NULL, 'MyService',

  NAME_FLAG_ATTACH_GLOBAL)))

  return EXIT_FAILURE;

 /* Становимся на петлю получения сообщений */

 while (flgWork) {

  if ((rcvid = MsgReceive(NameServer->chid, &MsgBuf,

   sizeof MsgBuf, NULL)) == -1) {

   printf('Ошибка при получении сервером MyService '

    'сообщения от клиента ');

   fflush(stdout);

   break;

  }

  if (!rcvid) {

   // Получен импульс

   switch(MsgBuf.hdr.code) {

   case _PULSE_CODE_DISCONNECT:

    /* Поскольку для канала установлен флаг _NTO_CHF_DISCONNECT, ядро

       автоматически не освобождает связи, установленные клиентом ранее.

       Сервер должен выполнить это со своей стороны сам, 'сознательно'

       удалив маршрут от себя обратно к клиенту */

    ConnectDetach(MsgBuf.hdr.scoid);

    break;

   case _PULSE_CODE_UNBLOCK;

    /* Клиент пытается разблокироваться, не дождавшись ответа по Reply. Надо

       выполнить какие-то действия, чтобы корректно (для себя)

       обработать эту ситуацию, и все-таки отпустить этого клиента - ему

       ведь надо! При этом импульсе в MsgBuf.hdr.value приходит rcvid */

    MsgReply(MsgBuf.hdr.value.sival_int, EAGAIN, NULL, 0);

    break;

   default:

    break;

   }

   continue;

   // вновь уходим на петлю приема сообщений

  }

  /* Полученное сообщение находится в диапазоне системных сообщений

     ввода/вывода. Не обрабатываем. */

  if (MsgBuf.hdr.type >= _IO_BASE && MsgBuf.hdr.type <= _IO_MAX) {

   MsgError(rcvid, ENOSYS);

   continue;

  }

  /* А вот это - сообщение для сервера. Обрабатываем. */

  if (MsgBuf.hdr.type <= 0x50001 || MsgBuf.hdr.type >= 0x500ff) {

   printf('Сервер получил сообщение неизвестно от'

    ' кого с меткой %#x ', MsgBuf.hdr.type);

   strcpy(BufReply, 'а кто это???');

  } else {

   printf('Сервер получил сообщение. '%s' ',

    MsgBuf.Buffer);

   strcpy(BufReply, 'а, это ты, клиент');

  }

  MsgReply(rcvid, EOK, BufReply, strlen(BufReply) + 1);

 }

 // Конец петли получения сообщений

 /* Отсоединяемся от службы глобальных имен */

 name_detach(NameServer, 0);

 return EXIT_SUCCESS;

}

Приложения-клиенты, которым надо использовать глобальную службу имен, могут использовать функцию API name_open(). В случае, когда служба обеспечивается несколькими серверами (интересная и очень полезная возможность, заключающаяся в том, что несколько серверов вправе на различных узлах сети объявить одну и ту же службу), правила связи со службой имен таковы:

• Если поставщик службы имеется на том же узле, что и приложение, запросившее службу,

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату