我一直试图绕过FIFO,想出了一个简单的服务器和客户端程序。
我没有尝试做任何花哨的事情,只是为了让一个过程能够扮演“服务器”的角色,这个过程将会聆听'对另一个进程传递的任何消息;客户。
这是我写的:
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
来阻止任何人写信{{1} }}。到目前为止一切顺利。
现在,考虑客户端:
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;
}
这是客户。也很简单的代码。当我使用./a.out
从shell运行它时,它可以工作 - 它发送消息,server.out
进程打印You sent %s to server.
问题是,当我通过客户端向服务器发送Quit
时,虽然a.out
进程会根据需要终止,但while
中的server.out
循环也会中断。意思是,read
不再阻止server.out
进程并等待其他客户端,而是服务器程序与客户端一起结束。
为什么会这样?即使在read
流程结束后,server.out
再次暂停a.out
也不应该吗?
答案 0 :(得分:9)
当我使用./server.out&在后台运行它时它在读取调用时被阻止并等待任何人写入clientToServer.fifo
实际上它会阻挡open
。这是FIFO工作的方式。 open
(在阻塞模式下)将阻塞,直到某些东西在另一端打开FIFO。
server.out中的while循环也会中断。意思是,read不再阻塞server.out进程并等待其他客户端,而是服务器程序结束
同样,这是正常行为。只有一个客户端进程连接到FIFO,因此当它关闭时,则发送EOF并退出服务器。如果多个客户端同时连接到FIFO,则在最后一个客户端关闭EOF之前,您不会看到EOF。如果您希望长时间运行的服务器连续为多个客户端提供服务,最简单的方法是将服务器的FIFO打开为读/写。这种方式总是有一个读写器 - 服务器本身 - 即使最后一个客户端退出也不会看到EOF。什么时候关闭服务器然后关闭服务器中的适当的一端,让大自然在真正的客户退出时采取自己的方式。
答案 1 :(得分:2)
当客户端退出时,它会关闭管道连接,这会导致服务器中的read
函数返回退出循环的0
。