umask(0); /* Получаем нужные нам права доступа */
&& errno!= EEXIST)
errExit("mkfifo %s", SERVER_FIFO);
if (serverFd == -1)
errExit("open %s", SERVER_FIFO);
/* Открываем дополнительный записывающий дескриптор,
чтобы никогда не получить символ конца файла */
if (dummyFd == -1)
errExit("open %s", SERVER_FIFO);
errExit("signal");
if (read(serverFd, &req, sizeof(struct request))
!= sizeof(struct request)) {
fprintf(stderr, "Error reading request; discarding\n");
continue; /* Либо частичное прочтение, либо ошибка */
}
/* Открываем клиентскую очередь FIFO (предварительно созданную клиентом) */
(long) req.pid);
if (clientFd == -1) { /* Открыть не удалось, отклоняем запрос */
errMsg("open %s", clientFifo);
}
/* Отправляем ответ и закрываем очередь FIFO */
resp.seqNum = seqNum;
if (write(clientFd, &resp, sizeof(struct response))
!= sizeof(struct response))
fprintf(stderr, "Error writing to FIFO %s\n", clientFifo);
if (close(clientFd) == -1)
errMsg("close");
seqNum += req.seqLen; /* Обновляем номер нашей последовательности */
}
}
pipes/fifo_seqnum_server.c
В листинге 44.8 приведен код клиента, выполняющего следующие действия.
• Создает очередь FIFO, которая будет использоваться для получения ответа от сервера
• Создает сообщение для сервера, состоящее из идентификатора клиентского процесса и числа (взятого из опционального аргумента командной строки), обозначающего длину последовательности, которую клиент хочет получить от сервера
• Открывает серверную очередь FIFO
• Открывает клиентскую очередь FIFO
Еще один момент, на который стоит обратить внимание, — обработчик выхода
Вот пример того, что можно увидеть при запуске клиентской и серверной программ:
$ ./fifo_seqnum_server &
[1] 5066
$ ./fifo_seqnum_client 3
0
$ ./fifo_seqnum_client 2
3
$ ./fifo_seqnum_client
5
Листинг 44.8. Клиент для сервера, генерирующего числовые последовательности
pipes/fifo_seqnum_client.c
#include "fifo_seqnum.h"
static char clientFifo[CLIENT_FIFO_NAME_LEN];
static void /* Вызывается при выходе для удаления клиентской очереди FIFO */
{
unlink(clientFifo);
}
int
main(int argc, char *argv[])
{
int serverFd, clientFd;
struct request req;
struct response resp;
if (argc > 1 && strcmp(argv[1], " — help") == 0)
usageErr("%s [seq-len…]\n", argv[0]);
/* Создаем нашу очередь FIFO (до отправки запроса, чтобы избежать состояния гонки) */
umask(0); /* Получаем нужные нам права доступа */
(long) getpid());
if (mkfifo(clientFifo, S_IRUSR | S_IWUSR | S_IWGRP) == -1
&& errno!= EEXIST)
errExit("mkfifo %s", clientFifo);
errExit("atexit");
/* Создаем запрос, открываем серверную очередь FIFO и отправляем запрос */
req.seqLen = (argc > 1)? getInt(argv[1], GN_GT_0, "seq-len"): 1;
if (serverFd == -1)
errExit("open %s", SERVER_FIFO);
sizeof(struct request))
fatal("Can't write to server");
/* Открываем нашу очередь FIFO, считываем и выводим ответ */
if (clientFd == -1)
errExit("open %s", clientFifo);
!= sizeof(struct response))