Читать «UNIX: взаимодействие процессов» онлайн - страница 48

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

Листинг 4.11. Клиент, связывающийся с сервером (листинг 4.10) с помощью канала FIFO

//fifocliserv/mainclient.с

1  #include "fifo.h"

2  int

3  main(int argc, char **argv)

4  {

5   int readfifo, writefifo;

6   size_t len;

7   ssize_t n;

8   char *ptr, fifoname[MAXLINE], buff[MAXLINE];

9   pid_t pid;

10  /* создание FIFO с включением в его имя PID */

11  pid = getpid();

12  snprintf(fifoname, sizeof(fifoname), "/tmp/fifo,%ld", (long) pid):

13  if ((mkfifo(fifoname, FILE_MODE) < 0) && (errno != EEXIST))

14   err_sys("can't create %s", fifoname);

15  /* инициализация буфера PID и пробелом */

16  snprintf(buff, sizeof(buff), "%ld ", (long) pid);

17  len = strlen(buff);

18  ptr = buff + len;

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

20  Fgets(ptr, MAXLINE – len, stdin);

21  len = strlen(buff); /* fgets() гарантирует завершающий 0 */

22  /* открытие FIFO сервера и запись в него полного имени и PID */

23  writefifo = Open(SERV_FIFO, O_WRONLY, 0);

24  Write(writefifo, buff, len);

25  /* открытие созданного FIFO; блокирование до открытия его сервером */

26  readfifo = Open(fifoname, O_RDONLY; 0);

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

28  while ((n = Read(readfifo, buff, MAXLINE)) > 0)

29   Write(STDOUT_FILENO, buff, n);

30  Close(readfifo);

31  Unlink(fifoname);

32  exit(0);

33 }

Создание канала

10-14 Идентификатор процесса клиента содержится в имени создаваемого им канала.

Формирование строки запроса

15-21 Запрос клиента состоит из его идентификатора процесса, одного пробела, полного имени запрашиваемого им файла и символа перевода строки. Строка запроса формируется в массиве buff, причем имя файла считывается из стандартного потока ввода.

Открытие канала сервера и отправка запроса

22-24 Клиент открывает канал сервера и записывает в него строку запроса. Если клиент окажется первым с момента запуска сервера, вызов open разблокирует сервер, заблокированный после сделанного им вызова open (с флагом O_RDONLY).

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

25-31 Ответ сервера считывается из канала и записывается в стандартный поток вывода, после чего канал клиента закрывается и* удаляется.

Сервер может быть запущен в одном из окон, а клиент — в другом, и программа будет работать так, как мы и рассчитывали. Ниже мы приводим только текст, выводимый клиентом:

solaris % mainclient /etc/shadow          файл, который нам нельзя читать

/etc/shadow: can't open. Permission denied

solaris % mainclient /etc/inet/ntp.conf  файл из двух строк

multicastclient 224.0.1.1

driftfile /etc/inet/ntp.drift 

Мы можем также связаться с сервером из интерпретатора команд, поскольку каналы FIFO обладают именами в файловой системе.