Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 [ 51 ] 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

Листинг 6.13 (продолжение)

42 Mesg sencl(writefd. &niesg):

43 }

44 }

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

svmsgmpxlq/cl ient niai n ,с

1 #include svmsg.h

2 void clientCint. int);

3 int

4 mainCint argc. char **argv)

6 int msqid:

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

8 msqid = MsggetCMQ KEY1, 0):

9 clientCmsqid. msqid): /* одна очередь в обе стороны */

10 exitCO):

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

svmsgmpxlq/client.с

1 #include mesg.h

2 void

3 ClientCint readfd. int writefd)

5 size t len;

6 ssize t n;

7 char *ptr:

8 struct mymesg mesg;

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

10 snprintfCmesg.mesg data, MAXMESGDATA, Id , Clong) getpidO):

11 len = strlen(mesg.mesg data);

12 ptr = mesg.mesg data + len;

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

14 FgetsCptr. MAXMESGDATA - len, stdin);

15 len = strlenCmesg.mesg data);

16 if Cmesg.mesg data[len-1] == Vn)

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

18 mesg.mesg len = len;

19 mesg.mesg type = 1;

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

21 Mesg sendCwritefd. &mesg);

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

23 mesg, mesg type = getpidO;

24 wliile С Cn = Mesg recv С readfd. &mesg)) > 0)

25 WriteCSTDOUTJILENO, mesg.mesg data, n);

26 }



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

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

дочерний процесс

родительский процесс

дочерний процесс


клиент 1

клиент 2

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

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

ПРИМЕЧАНИЕ -

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

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

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

ш svmsg, h (листинг 6.7);

Ш функция maiп сервера (листинг 6,12);

ш функция mesg send (листинг 4.13).

Функция main клиента приведена в листинге 6.16; она слегка изменилась по сравнению с листингом 6.14. Мы открываем очередь сервера с известным ключом (MQ KEY1) и создаем нашу собственную очередь с ключом IPC PRI VATE. Два идеи-



тификатора этих очередей становятся аргументами функции с1 i ent (листинг 6.17). После завершения работы клиента его персональная очередь удаляется.

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

svmsgmpxnq/cl i ent niai n. с

1 finclude svmsg.h

2 void clientCint. int);

3 int

4 mainCint argc. char **argv)

6 int readid. writeid;

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

8 writeid = MsggetСMQ KEY1. 0);

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

10 readid = MsggetClPC PRIVATE, SVMSG MODE IPC CREAT);

11 client Сreadid. writeid);

12 /* и удаляем нашу собственную очередь */

13 MsgctiCreadid, IPC RMID. NULL);

14 exitCO);

15 }

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

svmsgmpxnq/client.c

1 #include mesg.h

2 void

3 clientCint readid. int writeid)

5 size t len;

6 ssize t n;

7 char *ptr;

8 struct mymesg mesg;

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

10 snprintfCmesg.mesg data. MAXMESGDATA. %й . readid);

11 len = strlenCmesg.mesg data);

12 ptr = mesg.mesg data + len;

13 /* считываем имя фа11ла */

14 FgetsCptr. MAXMESGDATA - len. stdin);

15 len = strlenCmesg.mesg data);

16 if cmesg.mesg data[len-l] == \n)

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

18 mesg. mesgjen = len;

19 mesg. mesg Jype = 1;

20 /* отправляем идентификатор очереди и имя фа11ла серверу */

21 MesgjendCwriteid, &mesg);

22 /* считываем ответ из наше11 очереди и записываем его в stdout */



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 [ 51 ] 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.