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

#include <sys/neutrino.h>

int ConnectAttach( uint32_t nd,

pid_t pid,

int chid,

unsigned index,

int flags ); - присоединение к каналу

int MsgSend( int coid,

const void* smsg,

int sbytes,

void* rmsg,

int rbytes ); - отправка сообщения и принятия ответа от сервера

int ConnectDetach( int coid ); - разрыв соединения

Результат представлен на рис. 1.5.

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

Каждый клиент отправил сообщение серверу. При получении сервер ответил клиентам.

1.2.  Передача сообщений между двумя неродственными процессами

Рассмотрим передачу сообщений между двумя неродственными процессами. Для этого при запуске клиента будем указывать PID процесса-сервера.

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

#include <sys/neutrino.h>

#include <errno.h>

#include <process.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main () {

// Идентификаторы соединения и клиента

int chid, rcvid;

// Приёмный буфер и буфер для ответа

char receive_buf[50], reply_buf[50];

// Создание канала

chid = ChannelCreate(0);  

while(1) {

// Принимаем сообщение из канала chid

rcvid = MsgReceive(chid, &receive_buf, sizeof(receive_buf), NULL);

// Если не импульс, обрабатываем сообщение

if (rcvid) {

// Выведем текст принятого сообщения

printf("SERVER: message from client \"%s\"\n", &receive_buf);

// Запишем в буфер ответа сообщение для клиента

strcpy(reply_buf, "Hello from server!");

// Отправим ответ

printf("SERVER: send message \"%s\"\n", &reply_buf );

MsgReply(rcvid, EOK, &reply_buf, sizeof(reply_buf));

}

}

// Уничтожаем канал

ChannelDestroy(chid);

return EXIT_SUCCESS;

}

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

#include <sys/neutrino.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main (int argc, char* argv[]) {

if (argc != 2) {

printf("Wrong number of arguments\n");

return EXIT_FAILURE;

}

// Идентификатор соединения

int coid;

// Возвращаемое значение MsgSend

int status;

// PID клиента и сервера

int pid = getpid(), server_pid = atoi(argv[1]);

// Буфер отправляемого и принятого сообщений   

char send_buf[50], reply_buf[50];

// Устанавливаем соединение

coid = ConnectAttach(0, server_pid,  2, 0 ,0);

// Запишем в буфер текст сообщения для сервера 

sprintf(send_buf, "Hello from client with PID = %d", pid);

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

printf("Client: send message \"%s\"\n", &send_buf );

status = MsgSend(coid,  &send_buf, sizeof(send_buf), &reply_buf, sizeof(reply_buf));

if (status == -1) {

printf("Error of MsgSend\n");

return EXIT_FAILURE;

}

printf("Client: message \"%s\" from server\n", &reply_buf);

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

ConnectDetach(coid);

return EXIT_SUCCESS;

}

Результат представлен на рис. 1.6.

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

При подключении к каналу клиент послал сообщение, сервер его получил и отправил ответ.

1.3.  Передача сообщений с использованием регистрации префикса

Послать сообщение по установленному соединению - дело несложное, сложнее узнать PID сервера и CHID. Из всех способов удобнее всего два, основанные на механизме пространства путевых имён Администратора процессов.

Первый способ, настоятельно рекомендуемый компанией QNX Software Systems, - оформить сервер в виде администратора ресурсов.

Второй способ широко используется программистами, поскольку он чрезвычайно прост. Его мы и рассмотрим.

Идея заключается в том, что сервер регистрирует у Администратора процессов некоторое имя, называемое префиксом, при этом создаётся и сам канал. Администратор процессов сопровождает таблицу, где хранит соответствие между именем префикса и параметрами, нужными для установления соединения с этим каналом.