我正在尝试创建一个命名管道(FIFO)的简单示例。在这里,服务器将侦听来自客户端的消息,该消息在命名管道上写入,对两者都是通用的。要实现的特殊事情是FIFO应该是非阻塞的(使用O_NONBLOCK
)。
通过非阻止,我的意思是如果没有读者,作者应该在写作后立即返回。同样,如果没有消息(没有作者),读者应立即返回。
我已经创建了阻止版本,但它的工作正常。然后我尝试将其转换为非阻塞。
这是客户:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define FIFO "/tmp/myFIFO"
/*
This acts as the client, writing to the FIFO
*/
int main(int argc, char *argv[])
{
FILE *fp;
int fifo_fd;
if(argc != 2)
{
printf("Usage : ./fifo_client <message> \n");
exit(1);
}
fifo_fd = open(FIFO, O_WRONLY | O_NONBLOCK);
if(fifo_fd < 0)
{
perror("Error while open call");
exit(1);
}
fp = fdopen(fifo_fd, "w");
if(fp == NULL)
{
perror("Error while opening fd");
exit(1);
}
fputs(argv[1],fp);
/* Close the fp */
fclose(fp);
return 0;
}
这是服务器:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define FIFO "/tmp/myFIFO"
/*
This acts as a server waiting for strings to be written by the client, over the FIFO
*/
int main()
{
FILE *fp;
int fifo_fd;
char buf[1024];
/* Create a FIFO */
umask(0);
if(mkfifo(FIFO,0666) < 0) /* 0666 is read and write permission*/
{
perror("Error creating FIFO");
exit(1);
}
while(1) /*endless wait, keep reading strings and print*/
{
fifo_fd = open(FIFO, O_RDONLY | O_NONBLOCK);
if(fifo_fd < 0)
{
perror("Error while open call");
exit(1);
}
fp = fdopen(fifo_fd, "w");
if(fp == NULL)
{
perror("Error while opening fd");
exit(1);
}
if(!fgets(buf,1024,fp))
printf("Nothing to read\n");
else
printf("Message Recieved : %s\n", buf);
fclose(fp);
sleep(1);
}
return 0;
}
我先运行服务器。
其次,在第二个终端上,当我运行客户端时,我收到错误:
Error while open call: No such device or address
我错过了什么?我做了man
,参数似乎是正确的。
编辑
将open
和close
调用移出while循环,完成了这项工作。但是现在如果在没有启动服务器的情况下启动客户端,则会抛出以下错误:
打开电话时出错:没有此类设备或地址
文件系统/tmp/myFIFO
存在于文件系统上,必须由客户端使用。
答案 0 :(得分:0)
主要问题是在循环中打开和关闭文件。这毫无意义。打开和关闭之间的时间间隔非常短,您的客户必须点击它。它几乎没有机会这样做。 &#34;没有这样的设备或地址&#34;消息恰好发生,因为客户端错过文件打开时的瞬间。这是主要问题。尝试将open
,fopen
和fclose
移出服务器循环。
您还open
阅读但fopen
写作,但我认为这只是一个错字。这种组合不会运行。您需要将fopen
的模式更改为"r"
。
还有其他较小的问题。
open
,但有时打开会成功,写入将失败。stdio
作为管道是没有意义的。 read
和write
会很好。最后但同样重要的是,sleep
表示设计问题。实际上,在这个程序中阻塞I / O会更有意义。如果您只想尝试非阻塞I / O,可以使用sleep
,但在实际程序中应该避免使用。