Читать «UNIX: взаимодействие процессов» онлайн - страница 103
Уильям Ричард Стивенс
В листинге 6.14 приведен текст функции main клиента. Клиент открывает очередь сообщений, которая должна была быть создана сервером заранее.
Функция client, текст которой дан в листинге 6.15, обеспечивает всю обработку со стороны клиента. Эта функция представляет собой комбинацию программ из листингов 4.11 и 4.15. В первой программе клиент отсылал свой идентификатор и полное имя файла, а во второй программе использовались функции mesg_send и mesg_recv. Обратите внимание, что тип сообщений, запрашиваемых функцией mesg_recv, совпадает с идентификатором процесса клиента.
Функции client и server используют функции mesg_send и mesg_recv из листингов 6.9 и 6.11.
Листинг 6.13. Функция server
//svmsgmpx1q/server.c
1 #include "mesg.h"
2 void
3 server(int readfd, int writefd)
4 {
5 FILE *fp;
6 char *ptr;
7 pid_t pid;
8 ssize_t n;
9 struct mymesg mesg;
10 for (;;) {
11 /* считывание полного имени из канала IPC */
12 mesg.mesg_type = 1:
13 if ((n = Mesg_recv(readfd, &mesg)) == 0) {
14 err_msg("pathname missing");
15 continue;
16 }
17 mesg.mesg_data[n] = '\0'; /* полное имя */
18 if ((ptr = strchr(mesg.mesg_data, ' ')) == NULL) {
19 err_msg("bogus request: %s", mesg.mesg_data);
20 continue;
21 }
22 *ptr++ =0; /* ptr = полное имя */
23 pid = atol(mesg.mesg_data);
24 mesg.mesg_type = pid; /* для обратных сообщений */
25 if ((fp = fopen(ptr, "r")) == NULL) {
26 /* 4error: must tell client */
27 snprintf(mesg.mesg_data + n, sizeof(mesg.mesg_data) – n,
28 ": can't open. %s\n", strerror(errno));
29 mesg.mesg_len – strlen(ptr);
30 memmove(mesg.mesg_data, ptr, mesg.mesg_len);
31 Mesg_send(writefd, &mesg);
32 } else {
33 /* файл открыт, копируем клиенту */
34 while (Fgets(mesg.mesg_data, MAXMESGDATA, fp) != NULL) {
35 mesg.mesg_len = strlen(mesg.mesg_data);
36 Mesg_send(writefd, &mesg);
37 }
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() */