Читайте также:
|
|
В QNX обмен сообщениями является основной механизмом при взаимодействии процессов друг с другом. Микроядро ОС обеспечивает передачу сообщений. СРВ в QNX реализуются по модели «клиент/сервер». Программа, выполняющие функции сервера (уровень 1), является более «главной» по отношению к программе клиента (уровень 2), которая в свою очередь может быть сервером для клиента более низкого уровня (уровень 3) и она уже в свою очередь будет «главнее» программы третьего уровня иерархии и т.д. Клиент отправляет серверу сообщения. Сервер их получает, обрабатывает и отвечает клиенту. При таком способе обмена сообщениями возникает необходимость следовать строгой иерархии обмена. Поток своего уровня иерархии должен посылать сообщения (отвечать) потоку более низкого уровня, а не своего или высшего. Т.е. ответ идет от потока являющегося более главным (сервер) по отношению к потоку, который его запрашивает (клиент).
Приведем пример взаимодействия между двумя процессами на основе обмена сообщениями.
#include <stdio.h>
#include <sys/neutrino.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <process.h>
#include <sys/stat.h>
#include <fcntl.h>
//for write
#include <unistd.h>
void server(void *not_user)
{
int rcvid; //идентификатор отправителя
int chid; //идентификатор канала
char message[512];//буфер для отправки сообщения
int pid; //идентификатор процесса
pid = getpid(); // получение дескриптора процесса
//создание канала
Сервер должен создать канал, к которому будет присоединяться клиент при вызове функции ConnectAttach(). Канал создается с помощью функции ChannetCreate(), а уничтожается с помощью функции ChannelDestroy(). Для этого необходимо добавить заголовочный файл #include <sys/neutrino.h>.
chid = ChannelCreate(0);
После этого сервер создал канал с атрибутами канала, используемыми по умолчанию. После этого клиенты могут к нему подсоединиться и начать передачу сообщений. Для этого клиент использует функцию ConnectAttach(), которой необходимо указать дескриптор узла (Node descriptor – ND), идентификатор процесса (Process ID – PID) и идентификатор канала (Channel ID – CHID). Предположим, что два процесса работают на одном ПК. Для того, чтобы клиент смог определить PID и CHID, сервер записывает эти параметры в файл "/etc/mes2.pid" в формате PID/CHID.
//запись в файл идентификатора процесса и канала pid/chid
char *pname_file = "/etc/mes2.pid";
char buff[20];
int sizeread; //число байт, считанных из файла
int fd;
fd = open(pname_file, O_CREAT | O_RDWR | O_CREAT);//открытие файла
if (fd == -1){
печать сообщение об ошибке открытия файла
}
sprintf(buff, "%i/%d\n", pid, chid);//формирование массива для записи в файл
int size_written = write(fd, buff, sizeof(buff));//запись в файл
if(size_written!= sizeof(buff)){
печать сообщения об ошибке записи в файл
}
close(fd);
Далее идет непосредственно обработка сообщений от сервера. Она для сервера проходит в два этапа:
· этап приема сообщения (recive);
· этап ответа на сообщение (reply).
Рис.2.3.1. Использование функции MsgReceive() для ожидания сообщений от клиентов |
Для ожидания сообщений от клиентов используется функция MsgReceive(), рис.2.3.1.
int MsgReceive(int chid,//идентификатор канала
void *rmsg,//указатель на принимаемое сообщение
int rbytes,//размер сообщения
struct msg_info *info
);
Для ответа клиенту сервер использует функцию MsgReply().
int MsgReply(int rcvid, //идентификатор отправителя
int status,//значение анализируется клиентом
const void *msg,//указатель на отправляемое сообщение
int nbytes //размер сообщения
);
while(1){
//получение сообщения от клиента
rcvid = MsgReceive(chid, message, sizeof(message), NULL);
printf("server: message from client: %s \n", message);
printf("id client - rcvid = %X\n", rcvid);
//ответ сервера
strcpy(message,"das ist beantwort des servers");
MsgReply(rcvid, EOK, message, sizeof(message));
}
}
Задание 7
. Цель работы — для примера сервера определить тип сообщения, принимаемого от клиента.
Дата добавления: 2015-12-08; просмотров: 50 | Нарушение авторских прав