写入/读取/从FIFO文件 – Linux

我一直试图绕过FIFO,并提出了一个简单的服务器和客户端程序。
我并不想做任何奇怪的事情,只是为了让一个进程扮演“服务器”的angular色,这个进程将“监听”其他进程发送的任何消息; 客户端。
这是我写的:

server.c

#include<stdio.h> #include <fcntl.h> #include <stdlib.h> #define INGOING "clientToServer.fifo" #define BUFFER 200 int main(int argc, char *argv[]) { char in[BUFFER]; mkfifo(INGOING, 0666); printf("Welcome to server.\n"); printf("channel for sending messages to server is %s\n", INGOING); int in_fd=open(INGOING, O_RDONLY); if (in_fd==-1) { perror("open error"); exit(-1); } while (read(in_fd, in, BUFFER)>0) { printf("You sent %s to server.\n", in); } return 2; } 

正如你所看到的,这是非常直接的,当我用./server.out&在后台运行它时,它在read调用时被阻塞,并等待任何人写入clientToServer.fifo 。 到现在为止还挺好。

现在,考虑客户端:
client.c

 #include<stdio.h> #include<fcntl.h> #include<string.h> #define BUFFER 200 int main(int argc, char *argv[]) { char input[BUFFER]={0}; int out_fd=open("clientToServer.fifo", O_WRONLY); if (out_fd==-1) { perror("open error"); } while (1) { printf("What would you like to send to server? (send Quit to quit)\n"); fgets(input, BUFFER, stdin); if (input[strlen(input)-1]=='\n') { input[strlen(input)-1]='\0'; } if (strcmp(input, "Quit")==0) { printf("Bye!"); break; } if (write(out_fd, input, strlen(input))==-1) { perror("write error"); } } return 1; } 

这是客户。 也很简单的代码。 当我从shell运行./a.out时,它会工作 – 它发送消息, server.out进程打印You sent %s to server.
问题是,当我通过客户端将Quit发送到服务器时,虽然a.out进程根据需要终止, while server.outwhile循环server.out中断。 意思是, read不再阻塞server.out进程并等待其他客户端,而是服务器程序与客户端一起结束。
为什么发生这种情况? 即使在a.out过程结束之后,不应该再次挂起server.out吗?

当我使用./server.out在后台运行时,它在读取调用时被阻塞,并等待任何人写入到clientToserver.fifo

其实它阻止了open 。 这是FIFOs的工作方式。 open (处于阻塞模式)将阻塞,直到另一端打开FIFO。

server.out中的while循环也会中断。 这意味着,读取不再阻塞server.out进程并等待其他客户端,而是服务器程序结束

再次,这是正常的行为。 只有一个客户端进程连接到FIFO,所以当它关闭时,EOF被发送,服务器退出。 如果多个客户端同时连接到FIFO,则在最后一个客户端关闭之前,您将看不到EOF。 如果你想要一个长时间运行的服务器连续服务多个客户端,最简单的方法就是打开服务器的FIFO作为读/写。 这样总是有一个读写器 – 服务器本身 – 即使最后一个客户端退出,也不会看到EOF。 当关闭服务器的时候,关闭服务器中的适当的一端,让真正的客户端退出,让自然走向成熟。

当客户端退出时,关闭管道连接,导致服务器中的read功能返回0 ,退出循环。