Читать «UNIX: взаимодействие процессов» онлайн - страница 46
Уильям Ричард Стивенс
4.8. Один сервер, несколько клиентов
Преимущества канала FIFO проявляются более явно в том случае, когда сервер представляет собой некоторый длительно функционирующий процесс (например, демон, наподобие описанного в главе 12 [24]), не являющийся родственным клиенту. Демон создает именованный канал с вполне определенным известным именем, открывает его на чтение, а запускаемые впоследствии клиенты открывают его на запись и отправляют демону команды и необходимые данные. Односторонняя связь в этом направлении (от клиента к серверу) легко реализуется с помощью FIFO, однако необходимость отправки данных в обратную сторону (от сервера к клиенту) усложняет задачу. Рисунок 4.12 иллюстрирует прием, применяемый в этом случае.
Рис. 4.12. Один сервер, несколько клиентов
Сервер создает канал с известным полным именем, в данном случае /tmp/fifо.serv. Из этого канала он считывает запросы клиентов. Каждый клиент при запуске создает свой собственный канал, полное имя которого определяется его идентификатором процесса. Клиент отправляет свой запрос в канал сервера с известным именем, причем запрос этот содержит идентификатор процесса клиента и имя файла, отправку которого клиент запрашивает у сервера. В листинге 4.10 приведен текст программы сервера.
Листинг 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;