Книга: UNIX: взаимодействие процессов

6.7. Пример программы клиент-сервер

6.7. Пример программы клиент-сервер

Перепишем наш пример программы типа клиент-сервер из раздела 4.2 с использованием двух очередей сообщений. Одна из очередей предназначена для передачи сообщений от клиента серверу, а другая — в обратную сторону.

Заголовочный файл svmsg.h приведен в листинге 6.7. Мы подключаем наш стандартный заголовочный файл и определяем ключи для каждой из очередей сообщений.

Листинг 6.7. Заголовочный файл svmsg.h для программы клиент-сервер, использующей очереди сообщений

//svmsgcliserv/svmsg.h
1 #include "unpipc.h"
2 #define MQ_KEY1 1234L
3 #define MQ_KEY2 2345L

Функция main для сервера приведена в листинге 6.8. Программа создает обе очереди сообщений, и не беда, если какая-нибудь из них уже существует, потому что мы не указываем флаг IPC_EXCL. Функция server дана в листинге 4.16. Она вызывает наши собственные функции mesgsend и mesgrecv, новые версии которых будут приведены ниже.

Листинг 6.8. Функция main программы-сервера, использующей очереди сообщений

//svmsgcliserv/server_main.с
1  #include "svmsg.h"
2  void server(int, int);
3  int
4  main(int argc, char **argv)
5  {
6   int readid, writeid;
7   readid = Msgget(MQ_KEY1, SVMSG_MODE | IPC_CREAT);
8   writeid = Msgget(MQ_KEY2, SVMSG_MODE | IPC_CREAT);
9   server(readid, writeid);
10  exit(0);
11 }

Листинг 6.9. Функция main программы-клиента, использующей очереди сообщений

//svmsgcliserv/client_main.с
1  #include "svmsg.h"
2  void client(int, int);
3  int
4  main(int argc, char **argv)
5  {
6   int readid, writeid;
7   /* assumes server has created the queues */
8   writeid = Msgget(MQ_KEY1, 0);
9   readid = Msgget(MQ_KEY2, 0);
10  client(readid, writeid);
11  /* now we can delete the queues */
12  Msgctl(readid, IPC_RMID. NULL);
13  Msgctl(writeid, IPC_RMID, NULL);
14  exit(0);
15 }

В листинге 6.9 приведен текст функции main программы-клиента. Программа открывает две очереди сообщений и вызывает функцию client из листинга 4.15. Эта функция использует две другие: mesg_send и mesg_recv, которые будут приведены ниже.

И функция client, и функция server используют формат сообщений, изображенный в листинге 4.12. Для передачи и приема сообщений они используют функции mesg_send и mesg_recv. Старые версии этих функций, приведенные в листингах 4.13 и 4.14, вызывали write и read и работали с программными каналами и FIFO, так что нам придется переписать их для использования очередей сообщений. В листингах 6.10 и 6.11 приведены новые версии этих функций. Обратите внимание, что аргументы функций не изменились, поскольку первый целочисленный аргумент может содержать как целочисленный дескриптор программного канала или FIFO, так и целочисленный дескриптор очереди сообщений.

Листинг 6.10. Функция mesg_send, работающая с очередью сообщений System V

//svmsgcliserv/mesg_send.с
1 #include "mesg.h"
2 ssize_t
3 mesg_send(int id, struct mymesg *mptr)
4 {
5  return(msgsnd(id, &(mptr->mesg_type), mptr->mesg_len, 0));
6 }

Листинг 6.11. Функция mesg_recv, работающая с очередью сообщений System V

//svmsgcliserv/mesg_recv.с
1 #include "mesg.h"
2 ssize_t
3 mesg_recv(int id, struct mymesg *mptr)
4 {
5  ssize_t n;
6  n = msgrcv(id, &(mptr->mesg_type), MAXMESGDATA, mptr->mesg_type, 0);
7  mptr->mesg_len = n; /* количество возвращаемых данных */
8  return(n); /* –1 в случае ошибки, 0 – конец файла, иначе – >0 */
9 }

Оглавление книги


Генерация: 0.750. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз