Обмен сообщениями и импульсами в ОС QNX. Обмен сообщениями при стандартной организации модели "клиент-сервер", управляемой по запросу, страница 7

2.2.  Использование MsgDeliverEvent

Рассмотрим использование функции MsgDeliverEvent().

Заголовочный файл header.h:

struct my_msg

{

short type;

struct sigevent event;

};

#define MY_PULSE_CODE _PULSE_CODE_MINAVAIL+5

#define MSG_GIVE_PULSE _IO_MAX+4

#define MY_SERV "my_server_name"

Программа server4.c:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#include <sys/neutrino.h>

#include <sys/iomsg.h>

#include <sys/iofunc.h>

#include <sys/dispatch.h>

#include "header.h"

int main() {

int rcvid;

struct my_msg msg;

name_attach_t *attach;

// Регистрация префикса и создание канала

if ( (attach = name_attach( NULL, MY_SERV, 0 )) == NULL) {

printf("Server: failed to attach name, errno %d\n", errno );

return EXIT_FAILURE;

}   

// Ожидание сообщения от клиента

rcvid = MsgReceive( attach->chid, &msg, sizeof( msg ), NULL );

if (rcvid) {

// Отвечаем клиенту сразу

MsgReply(rcvid, 0, NULL, 0);

if ( msg.type == MSG_GIVE_PULSE ) {

// Делаем временную задержку, имитирующую обработку данных сервером

printf("Server: I'm work\n");

sleep(2);

// Доставляем событие клиенту

MsgDeliverEvent( rcvid, &msg.event );

printf("Server: delivered event\n");

} else {

printf("Server: unexpected message\n");

}   

}

name_detach(attach, 0);

return EXIT_SUCCESS;

}

Программа client4.c:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#include <sys/neutrino.h>

#include <sys/iomsg.h>

#include "header.h"

int main() {

int chid, coid, srv_coid, rcvid;

struct my_msg msg;

struct _pulse pulse;

// Создание канала для получения пульса от сервера

chid = ChannelCreate( 0 );

// Создаём соединение

coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );

// Заполнение event-структуры для пульса

SIGEV_PULSE_INIT( &msg.event, coid, SIGEV_PULSE_PRIO_INHERIT, MY_PULSE_CODE, 0 );

msg.type = MSG_GIVE_PULSE;

// Присоединение к каналу

if ((srv_coid = name_open( MY_SERV, 0 )) == -1) {

printf("Failed to find server");

return EXIT_FAILURE;

}         

// Отправляем сообщение

MsgSend( srv_coid, &msg, sizeof(msg), NULL, 0 );

printf("Client: I'm work\n");

// Ожидаем пульс от сервера

rcvid = MsgReceivePulse( chid, &pulse, sizeof( pulse ), NULL );

printf("Client: got pulse with code %d, waiting for %d\n", pulse.code,

MY_PULSE_CODE );

// Закрываем соединение

name_close(coid);

return EXIT_SUCCESS;

}

Результат выполнения программ представлен на  рис. 1.11.

Рис. 1.11. Результат

Как видно из результатов выполнения программ, клиент после отправки сообщения серверу может продолжать работу, как и собственно сервер. После обработки сообщения сервер уведомляет клиента о выполнении работы, посылая импульс с помощью команды MsgDeliverEvent().

2.3. Отправка импульса по завершению обработки прерывания

Рассмотрим программу, отправляющую импульс при нажатии любой клавиши клавиатуры.

Программа server5.c:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#include <sys/dispatch.h>

#include <sys/neutrino.h>

#define MY_SERV "my_server_name"

int main() {

struct _pulse pulse;

name_attach_t *attach;

// Регистрация префикса и создание канала

if ( (attach = name_attach( NULL, MY_SERV, 0 )) == NULL) {

printf("Server: failed to attach name\n" );

return EXIT_FAILURE;

}   

while (1) {

// Ожидание пульса от клиента

MsgReceivePulse(attach->chid, &pulse, sizeof(pulse), NULL);

if (pulse.code != _PULSE_CODE_DISCONNECT) {

printf("Server: pulse from client: pulse.code = %d, pulse.value = %d\n", pulse.code, pulse.value);

}

else {

printf("Server: disconnect pulse from client\n");

}

}

name_detach(attach, 0);

return EXIT_SUCCESS;

}