我在C.ÇFIFO的 - 如何读取服务器的标准输入,同时等待客户端请求
我有这样的服务器代码,使用Linux的命名管道实现一个简单的IPC系统:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "external/paths.h"
#include "external/sv.h"
#include "external/tags.h"
int main(int argc, char *argv[])
{
int fd, bytes_read;
char request[200];
// create fifo
mknod(FIFO_SERVER, S_IFIFO | 0666, 0);
puts("Servidor initialized.\nWaiting for client requests.");
// open created fifo
fd = open(FIFO_SERVER, O_RDONLY);
while(1)
{
if((bytes_read = read(fd, request, LEN_CL_REQUEST)) == -1)
perror("error read()");
if(bytes_read == 0)
continue;
if(bytes_read > 0)
{
printf("Request read: %s\n", request);
// answer back
}
}
close(fd);
unlink(FIFO_SERVER);
return 0;
}
我因为我的问题只与服务器有关,因此忽略客户端。沟通工作正常,我可以阅读客户的要求,我可以回答他们。现在,假设我想在任何时候能够在按下'Q'键时退出服务器..我不能这样做,因为我的代码阻止了read
语句等待另一个客户端请求,所以我有没办法读取stdin
..
是这样的可能吗?我正在考虑像非阻塞read
声明,并尝试读取stdin
几秒钟,然后再次检查传入的请求..我一直在寻找,但我还没有发现任何类似的东西。
UPDATE:
我跟让 - 巴蒂斯特Yunès方法,但事实证明,select
只检测FIFO的事件,我真的不知道为什么。
这是代码我测试:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int result, fd, maxDescriptor;
char input[20], texto[100];
mknod("fifo", S_IFIFO | 0666, 0);
fd = open("fifo", O_RDWR); // RDWR to avoid EOF return to select
fd_set readset;
FD_ZERO(&readset);
FD_SET(fileno(stdin), &readset);
FD_SET(fd, &readset);
maxDescriptor = fileno(stdin) > fd ? fileno(stdin) : fd;
while(1)
{
result = select(maxDescriptor+1, &readset, NULL, NULL, NULL);
if(result == -1)
perror("select()");
else if(result)
{
puts("data available.");
if(FD_ISSET(fileno(stdin), &readset))
{
scanf("%s", input);
printf("%s\n", input);
if(strcmp(input, "Q") == 0)
break;
}
if(FD_ISSET(fd, &readset))
{
read(fd, texto, 100);
printf("lido:\n%s\n", texto);
}
}
else
puts("no data.");
}
unlink("fifo");
return 0;
}
更新2:
正如让 - 巴蒂斯特Yunès指出,有需要重新FD_SET,因为它不会自动复位。
下面是最终的工作代码:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int result, fd, maxDescriptor;
char input[20], texto[100];
mknod("fifo", S_IFIFO | 0666, 0);
fd = open("fifo", O_RDWR); // RDWR to avoid EOF return to select
fd_set readset;
FD_ZERO(&readset);
FD_SET(fileno(stdin), &readset);
FD_SET(fd, &readset);
maxDescriptor = fileno(stdin) > fd ? fileno(stdin) : fd;
while(1)
{
result = select(maxDescriptor+1, &readset, NULL, NULL, NULL);
if(result == -1)
perror("select()");
else if(result)
{
puts("data available.");
if(FD_ISSET(fileno(stdin), &readset))
{
scanf("%s", input);
printf("%s\n", input);
if(strcmp(input, "Q") == 0)
break;
}
if(FD_ISSET(fd, &readset))
{
read(fd, texto, 100);
printf("lido:\n%s\n", texto);
}
FD_SET(fileno(stdin), &readset);
FD_SET(fd, &readset);
}
else
puts("no data.");
}
unlink("fifo");
return 0;
}
选择或投票将让您阻止等待多个文件描述符和解锁时,他们中任何一个准备读或写(查找选择) –
你也可以考虑使用异步I/O编写代码。 “libevent”是一个很好的c库,可以简化编写异步代码。 –
服务器通常无限期地运行服务,不读取标准输入。他们只能读取通讯频道,并且可以通过脚本启动或停止(杀死)。 – kjohri