Главная страница Взаимодействие нетривиальных процессов
сообщение 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):
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |