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

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

второй аргумент функций msgsnd и msgrcv <-mesgjen -

mesgjen

mesg type

mesg data

сообщение System V: msgbufO используется с очередями сообщений System V, функциями msgsnd и msgrcv

Наше сообщение: структура mymesgO используется с профаммными каналами и FIFO, функциями write и read

Рис. 4.13. Структура mymesg

Мы определяем две функции для отправки и приема сообщений. В листинге 4.13 приведен текст функции mesg send, а в листинге 4.14 - функции mesg recv.

Листинг 4.13. Функция mesg send

pi pemesg/mesg send.с

1 #include mesg.h

2 ssi ze t

3 mesg send(int fd. struct mymesg *mptr)

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

7 struct mymesg {

8 long niesg len: количество байтов в rnesg data. может быть О

9 long niesg type: THn сообщения, должен быть > О

10 char mesg data[MAXMESGDATA]:

11 }:

12 ssizet niesg send(int. struct mymesg *):

13 void Mesg send(int. struct mymesg *);

14 ssize t mesg recv(int. struct mymesg *):

15 ssizej Mesg recv(int. struct mymesg *):

Каждое сообщение содержит в себе информацию о своем типе (niesg type), причем значение этой переменной должно быть больше нуля. Пока мы будем игао-рировать это поле в записи, но вернемся к нему в главе 6, где описываются очереди сообщений System V. Каждое сообщение также обладает длиной, которая может быть и нулевой. Структура mymesg позволяет предварить каждое сообщение информацией о его типе и длине вместо использования символа перевода строки для сигнализации конца сообщения. Ранее мы отметили два преимущества этого подхода: получатель не должен сканировать все принятые байты в поисках конца сообщения и отсутствует необходимость исключать появление разделителя в самих данных.

На рис. 4.13 изображен вид структуры mymesg и ее использование с каналами, FIFO и очередями сообщений System V.

второй аргумент функций write и read



5 returnCwriteCfd, mptr. MESGHDRSIZE + mptr->rnesgjen)):

Листинг 4.14. Функция mesg recv

/ /pi pernesg/rnesg recv. с

1 #include mesg.h

2 ssize t

3 niesg recv(int fd. struct mymesg *mptr)

5 s1ze t len;

6 ssize t n:

8 /* считывание заголовка сообщения для определения его длины */

9 if ( (п - ReadCfd. mptr. MESGHDRSIZE)) - 0)

10 return(O); /* end of file */

11 else if (n !- MESGHDRSIZE)

12 err quit( message header: expected %й. got %й . MESGHDRSIZE. n);

13 if ( (len - mptr->mesgjen) > 0)

14 if ( (n - ReadCfd. mptr->mesg data. len)) !- len)

15 err quit( message data: expected %й. got *d . len. n):

16 return(len):

17 }

Теперь для каждого сообщения функция read вызывается дважды: один раз для считывания длины, а другой - для считывания самого сообщения (если его длина больше 0).

ПРИМЕЧАНИЕ-

Внимательные читатели могли заметить, что функция mesg recv проверяет наличие всех возможных ошибок и прекращает работу при их обнаружении. Однако мы все же определили функцию-обертку Mesg recv и вызываем из наших программ именно ее - для единообразия.

Изменим теперь функции с1 lent и server, чтобы воспользоваться новыми функциями mesg send и mesg recv. В листинге 4.15 приведен текст функции-клиента.

Листинг 4.15. Функция client с использованием сообщений

pipemesg/client.c

1 #include mesg.h

2 void

3 ClientCint readfd. int writefd)

5 size t len;

6 ssize t n;

7 struct mymesg mesg;

8 /* считывание полного имени */

9 Fgets(mesg.mesg data. MAXMESGDATA. stdin);

10 len - strlen(mesg.mesg data);

11 if (mesg.mesg data[len-l] - \n)

12 len--; /* удаление перевода строки из fgetsО */

13 mesg. mesgj en - 1 en: продолжение



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

14 rnesg.rnesg type = 1:

15 /* запись полного имени в канал IPC */

16 Mesg send(writefd. Smesg):

17 /* считывание из канала IPC. запись в stdout */

18 while ( (n - Mesg recv(readfd. Smesg)) > 0)

19 WriteCSTDOUTJILENO. mesg.mesgjata. n):

20 }

Считывание имени файла и отправка его серверу

8-16 Полное имя считывается из стандартного потока ввода и затем отправляется на сервер с помощью функщ1И mesg send.

Считывание содержимого файла или сообщения об ошибке от сервера

17-19 Клиент вызывает функцию mesg recv в цикле, считывая все приходящие от сервера сообщения. По соглашению, когда mesg recv возвращает нулевую длину сообщения, это означает конец передаваемых сервером данных. Мы увидим, что сервер добавляет символ перевода строки к каждому сообщению, отправляемому клиенту, поэтому пустая строка будет иметь длину сообщения 1. В листинге 4.16 приведен текст функции-сервера.

Листинг 4.16. Функция server, использующая сообщения

pipemesg/server.c

1 #include mesg.h

2 void

3 serverCint readfd. int writefd)

5 FILE *fp:

6 ssize t n;

7 struct mymesg mesg;

8 /* считывание полного имени из канала */

9 mesg.mesg type - 1;

10 if ( (n = Mesg recv(readfd. &mesg)) - 0)

11 err quit( pathname missing ):

12 mesg.mesg data[n] = \0: /* полное имя. завершающееся О */

13 if ( (fp = fopen(mesg.mesg data. r )) - NULL) {

14 /* ошибка, нужно сообщить клиенту */

15 snprintf(mesg.mesg data + n. sizeof(mesg.mesg data) - n.

16 : cant open. *s\n . strerror(errno));

17 mesg.mesgjen = strlen(mesg.mesg data):

18 Mesg send(writefd. &mesg);

19 } else {

20 /* файл успешно открыт, передача данных */

21 while (Fgets(mesg.mesg data. MAXMESGDATA. fp) !- NULL) {

22 mesg.mesgjen - strlen(mesg.mesg data):

23 Mesg send(writefd. &mesg):



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.
Копирование материалов разрешено исключительно при условии цититирования.