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

на главную - закладки

Жанры

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

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

Шрифт:
Листинг 4.10. Сервер, обслуживающий несколько клиентов с помощью канала FIFO

//fifocliserv/mainserver.с

1 #include "fifo.h"

2 void server(int, int);

3 int

4 main(int argc, char **argv)

5 {

6 int readfifo, writefifo, dummyfd, fd;

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

8 pid_t pid;

9 ssize_t n;

10 /* создание FIFO сервера с известным именем. ОК, если уже существует */

11 if ((mkfifo(SERV_FIFO, FILE_MODE) < 0) && (errno != EEXIST))

12 err_sys("can't create %s", SERV_FIFO);

13 /* открытие FIFO-cepвepa на чтение */

14 readfifo = Open(SERV_FIFO, O_RDONLY, 0);

15 dummyfd = Open(SERV_FIFO, O_WRONLY, 0); /* не используется */

16 while ((n = Readline(readfifo, buff, MAXLINE)) > 0) {

17 if (buff[n-1] == '\n')

18 n--; /* delete newline from readline */

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

20 if ((ptr = strchr(buff, ' ')) == NULL) {

21 err_msg("bogus request: ls", buff);

22 continue;

23 }

24 *ptr++ = 0; /* идентификатор процесса, указатель на имя файла */

25 pid = atol(buff);

26 snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long) pid);

27 if ( (writefifo = open(fifoname, O_WRONLY, 0)) < 0) {

28 err_msg("cannot open: ls", fifoname);

29 continue;

30 }

31 if ((fd = open(ptr, O_RDONLY)) < 0) {

32 /* ошибка, нужно сообщить клиенту */

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

34 strerror(errno));

35 n = strlen(ptr);

36 Write(writefifo, ptr, n);

37 Close(writefifo);

38

39 } else {

40 /* успешное открытие, копируем файл */

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

42 Write(writefifo, buff, n);

43 Close(fd);

44 Close(writefifo);

45 }

46 }

47 }

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

10-15 Сервер создает канал FIFO с известным именем, обрабатывая ситуацию, когда такой канал уже существует. Затем этот канал открывается дважды: один раз только для чтения, а второй — только для записи. Дескриптор readfifo используется для приема запросов от клиентов, а дескриптор dummyfd не используется вовсе. Причина, по которой нужно открыть канал для записи, видна из табл. 4.1. Если канал не открыть на запись, то при завершении работы очередного клиента этот канал будет опустошаться и сервер будет считывать 0, означающий конец файла. Пришлось бы каждый раз закрывать канал вызовом close, а затем заново открывать его с флагом O_RDONLY, что приводило бы к блокированию демона до подключения следующего клиента. Мы же всегда будем иметь дескриптор, открытый на запись, поэтому функция read не будет возвращать 0, означающий конец файла, при отсутствии клиентов. Вместо этого сервер просто будет блокироваться при вызове read, ожидая подключения следующего клиента. Этот трюк упрощает код программы-сервера и уменьшает количество вызовов open для канала сервера.

При запуске сервера первый вызов open (с флагом O_RDONLY) приводит к блокированию процесса до появления первого клиента, открывающего канал сервера на запись (см. табл. 4.1). Второй вызов open (с флагом O_WRONLY) не приводит к блокированию, поскольку канал уже открыт на запись. 

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

16 Каждый запрос, принимаемый от клиента, представляет собой одну строку, состоящую из идентификатора процесса, пробела и полного имени требуемого файла. Эта строка считывается функцией readline (приведенной в [24, с.79]).

Анализ запроса клиента

17-26 Символ перевода строки, возвращаемый функцией readline, удаляется. Этот символ может отсутствовать только в том случае, если буфер был заполнен, прежде чем был обнаружен символ перевода строки, либо если последняя введенная строка не была завершена этим символом. Функция strchr возвращает указатель на первый пробел в этой строке, который затем увеличивается на единицу, чтобы он указывал на первый символ полного имени файла, следующего за пробелом. Полное имя канала клиента формируется из его идентификатора процесса, и этот канал открывается сервером на запись.

Открытие файла и отправка его в FIFO клиента

27-44 Оставшаяся часть кода пpoгрaммы-cepвepa аналогична функции server из листинга 4.3. Программа открывает файл; если при этом возникает ошибка — клиенту отсылается сообщение о ней. Если открытие файла завершается успешно, его содержимое копируется в канал клиента. После завершения копирования открытый сервером «конец» (дескриптор) канала клиента должен быть закрыт с помощью функции close, чтобы функция read вернула пpoгрaммe-клиeнтy значение 0 (конец файла). Сервер не удаляет канал клиента; клиент должен самостоятельно позаботиться об этом после приема от сервера символа конца файла. Текст пpoгрaммы-клиeнтa приведен в листинге 4.11.

Листинг 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;

Поделиться:
Популярные книги

На гребне обстоятельств

Шелег Дмитрий Витальевич
7. Живой лед
Фантастика:
фэнтези
5.25
рейтинг книги
На гребне обстоятельств

Путь Князя. Возрождение. Часть 2

Рокотов Алексей
7. Путь князя
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
Путь Князя. Возрождение. Часть 2

Темная сторона. Том 1

Лисина Александра
9. Гибрид
Фантастика:
технофэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Темная сторона. Том 1

Забытые боги

Рокотов Алексей
4. Путь князя
Фантастика:
фэнтези
рпг
попаданцы
5.00
рейтинг книги
Забытые боги

Черный Маг Императора 8

Герда Александр
8. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 8

Иной. Том 1. Школа на краю пустыни

Amazerak
1. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.75
рейтинг книги
Иной. Том 1. Школа на краю пустыни

Измена. Свадьба дракона

Белова Екатерина
Любовные романы:
любовно-фантастические романы
эро литература
5.00
рейтинг книги
Измена. Свадьба дракона

Пламенев. Книга VIII

Карелин Сергей Витальевич
8. Пламенев
Фантастика:
аниме
уся
сказочная фантастика
фэнтези
фантастика: прочее
5.00
рейтинг книги
Пламенев. Книга VIII

Ермак. Регент

Валериев Игорь
10. Ермак
Фантастика:
попаданцы
альтернативная история
4.75
рейтинг книги
Ермак. Регент

Наша навсегда

Зайцева Мария
2. Наша
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Наша навсегда

Я все еще не князь. Книга XV

Дрейк Сириус
15. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я все еще не князь. Книга XV

Развод в 45. От любви до ненависти

Гофман Крис
6. Развод
Любовные романы:
остросюжетные любовные романы
5.40
рейтинг книги
Развод в 45. От любви до ненависти

Инженерный Парадокс 9

Cyberdawn
9. Инженерный Парадокс
Фантастика:
боевая фантастика
юмористическое фэнтези
попаданцы
5.00
рейтинг книги
Инженерный Парадокс 9

Диверсант

Вайс Александр
2. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Диверсант