Чтение онлайн

ЖАНРЫ

UNIX: взаимодействие процессов

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

Шрифт:
Листинг 6.12. Функция main сервера

//svmsgmpx1q/server_main.с

1 #include "svmsg.h"

2 void server(int, int);

3 int

4 main(int argc, char **argv)

5 {

6 int msqid;

7 msqid = Msgget(MQ_KEY1, SVMSG_MODE | IPC_CREAT);

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

9 exit(0);

10 }

Функция server

обеспечивает работу сервера. Ее текст приведен в листинге 6.13. Эта функция представляет собой комбинацию листинга 4.10 — нашего сервера FIFO, считывавшего команды, состоявшие из идентификатора процесса и полного имени файла, — и листинга 4.16, в котором использовались функции mesg_send и mesg_recv. Обратите внимание, что идентификатор процесса, отправляемый клиентом, используется в качестве типа для всех сообщений, отправляемых сервером этому клиенту. Эта функция представляет собой бесконечный цикл, в котором считываются запросы клиентов и отсылаются запрошенные файлы. Этот сервер является последовательным (см. раздел 4.9).

В листинге 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 */

18 mesg.mesg_len = len;

19 mesg.mesg_type = 1;

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

21 Mesg_send(writefd, &mesg);

Поделиться с друзьями: