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

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

Функция client приведена в листинге 4.2.

Листинг 4.2. Функция client для приложения типа клиент-сервер с двумя каналами

//pipe/client.с

1  #include "unpipc.h"

2  void

3  client(int readfd, int writefd)

4  {

5   size_t len;

6   ssize_t n;

7   char buff[MAXLINE];

8   /* получение полного имени файла */

9   Fgets(buff, MAXLINE, stdin);

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

11  if (buff[Len-l] == ' \n' )

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

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

14  Write(writefd, buff, len);

15  /* считывание из канала, вывод в stdout */

16  while ((n = Read(readfd, buff, MAXLINE)) > 0)

17   Write(STDOUT_FILENO, buff, n);

18 }

Считывание полного имени из стандартного потока ввода

8-14 Полное имя файла считывается из стандартного потока ввода и записывается в канал после удаления завершающего символа перевода строки, возвращаемого функцией fgets.

Копирование из канала в стандартный поток вывода

15-17 Затем клиент считывает все, что сервер направляет в канал, и записывает эти данные в стандартный поток вывода. Ожидается, что это будет содержимое файла, но в случае его отсутствия будет принято и записано в стандартный поток вывода сообщение об ошибке.

В листинге 4.3 приведена функция server.

Листинг 4.3. Функция server для приложения клиент-сервер с двумя каналами

//pipe/server.c

1  #include "unpipc.h"

2  void

3  server(int readfd, int writefd)

4  {

5   int fd;

6   ssize_t n;

7   char buff[MAXLINE+1];

8   /* получение полного имени из канала IPC */

9   if ((n = Read(readfd, buff, MAXLINE)) == 0)

10   err_quit("end-of-file while reading pathname"):

11  buff[n] = '\0'; /* полное имя завершается 0 */

12  if ((fd = open(buff, O_RDONLY)) < 0) {

13   /* 4error: must tell client */

14   snprintf(buff + n, sizeof(buff) – n, ": can't open. %s\n".

15   strerror(errno)):

16   n = strlen(buff);

17   Write(writefd, buff, n);

18  } else {

19   /* файл успешно открыт и копируется в канал */

20   while ( (n = Read(fd, buff, MAXLINE)) > 0)

21    Write(writefd, buff, n);

22   Close(fd);

23  }

24 }

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

8-11 Записанное в канал клиентом имя файла считывается сервером и дополняется завершающим символом с кодом 0 (null-terminated). Обратите внимание, что функция read возвращает данные, как только они помещаются в поток, не ожидая накопления некоторого их количества (MAXLINE в данном примере).

Открытие файла, обработка возможной ошибки

12-17 Файл открывается для чтения и при возникновении ошибки сообщение о ней возвращается клиенту с помощью канала. Для получения строки с соответствующим значению переменной errno сообщением об ошибке вызывается функция strerror (в книге [24, с. 690-691] вы найдете более подробный рассказ об этой функции).

Копирование из файла в канал

18-23 При успешном завершении работы функции open содержимое файла копируется в канал.