Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

Стивенс Уильям Ричард

Шрифт:

38 Fclose(fp);

39 }

40 /* сообщение нулевой длины заканчивает связь */

41 mesg.mesg_len = 0;

42 Mesg_send(writefd, &mesg);

43 }

44 }

Листинг 6.14. Функция main клиента

//svmsgmpx1q/client_main.c

1 #include "svmsg.h"

2 void client(int, int);

3 int

4 main(int argc, char **argv)

5 {

6 int msqid;

7 /* сервер должен был создать очередь */

8 msqid = Msgget(MQ_KEY1, 0);

9 client(msqid, msqid); /* одна очередь в обе стороны */

10 exit(0);

11 }

Листинг 6.15. Функция client

//svmsgmpx1q/client.с

1 #include "mesg.h"

2 void

3 client(int readfd, int writefd)

4 {

5 size_t len;

6 ssize_t n;

7 char *ptr;

8 struct mymesg mesg;

9 /* инициализируем буфер идентификатором процесса и пробелом */

10 snprintf(mesg.mesg_data, MAXMESGDATA. "%ld ", (long) getpid);

11 len = strlen(mesg.mesg_data);

12 ptr = mesg.mesg_data + len;

13 /* считываем полное имя файла */

14 Fgets(ptr, MAXMESGDATA – len, stdin);

15 len = strlen(mesg.mesg_data);

16 if (mesg.mesg_data[len-1] == '\n')

17 len--; /* удаляем перевод строки fgets */

18 mesg.mesg_len = len;

19 mesg.mesg_type = 1;

20 /* записываем PID и имя файла в канал IPC */

21 Mesg_send(writefd, &mesg);

22 /* считываем из канала IPC, записываем в stdout */

23 mesg.mesg_type = getpid;

24 while ((n = Mesg_recv(readfd, &mesg)) > 0)

25 Write(STDOUT_FILENO, mesg.mesg_data, n);

26 }
 

Пример: одна очередь для каждого клиента

Изменим теперь предыдущий пример таким образом, чтобы все запросы клиентов передавались по одной очереди, но для отправки ответов использовалась бы отдельная очередь для каждого клиента. На рис. 6.3 изображена схема такого приложения. 

Рис. 6.3. Одна очередь для сервера и по одной для каждого клиента

Ключ очереди сервера должен быть известен клиентам, а сами клиенты создают свои очереди с ключом IPC_PRIVATE. Вместо передачи серверу идентификатора процесса клиенты сообщают ему идентификатор своей очереди, в которую сервер направляет свой ответ. Этот сервер является параллельным: для каждого нового клиента порождается отдельный процесс.

ПРИМЕЧАНИЕ

При такой схеме может возникнуть проблема в случае «гибели» клиента, потому что тогда сообщения останутся в его очереди навсегда (по крайней мере до перезагрузки ядра или явного удаления очереди другим процессом).

Нижеследующие заголовочные файлы и функции не претерпевают изменений по сравнению с предыдущими версиями:

■ mesg.h (листинг 4.12);

■ svmsg.h (листинг 6.7);

■ функция main сервера (листинг 6.12);

■ функция mesg_send (листинг 4.13).

Функция main клиента приведена в листинге 6.16; она слегка изменилась по сравнению с листингом 6.14. Мы открываем очередь сервера с известным ключом (MQ_KEY1) и создаем нашу собственную очередь с ключом IPC_PRIVATE. Два идентификатора этих очередей становятся аргументами функции client (листинг 6.17). После завершения работы клиента его персональная очередь удаляется.

Листинг 6.16. Функция main клиента

//svmsgmpxnq/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 /* сервер должен создать свою очередь */

8 writeid = Msgget(MQ_KEY1, 0);

9 /* мы создаем свою собственную очередь */

  • Читать дальше
  • 1
  • ...
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: