c - Linux : Creating a simple non-blocking server and client to communicate over named pipes

标签 c linux named-pipes

我正在尝试创建命名管道 (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,参数似乎是正确的。

编辑

openclose 调用移出 while 循环,完成了这项工作。但是现在如果在没有启动服务器的情况下启动客户端,则会抛出以下错误:

打开调用时出错:没有这样的设备或地址

文件 /tmp/myFIFO 存在于服务器先前执行的文件系统中,必须由客户端使用。

最佳答案

主要问题是循环打开和关闭文件。这是没有意义的。打开和关闭之间的时间间隔很短,您的客户必须击中它。它几乎没有机会这样做。 “没有这样的设备或地址”消息恰恰是因为客户端错过了文件打开的瞬间。这是主要问题。尝试将 openfopenfclose 移出服务器循环。

您也 opening 用于阅读,fopening 用于写作,但我想这只是一个错字。该组合不会运行。您需要将fopen 的模式更改为"r"

还有其他较小的问题。

  1. 您没有检查客户端中的错误。在您的程序中,客户端大部分时间都无法打开,但有时打开会成功而写入会失败。
  2. 在这个程序中为管道使用stdio 毫无意义。 readwrite 就可以了。

最后但同样重要的是,sleep 表示存在设计问题。事实上,在这个程序中阻塞 I/O 会更有意义。如果您只想试验非阻塞 I/O,可以使用 sleep,但在实际程序中应避免使用。

关于c - Linux : Creating a simple non-blocking server and client to communicate over named pipes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37508395/

相关文章:

c++ - 将 yyin 设置为 "emulated"文件*?

c - 翻译单元中 `static` 定义和 `extern declaration` 的顺序

linux - 如何在单个命令中检查远程机器上的非空目录

linux - 如何知道gcc安装的确切位置

php执行sh文件

php - 使用php写入linux中的管道

ffmpeg - 使用 FFMPEG 将连续视频文件流式传输到 RTMP 服务器

c++ - 浮点值比较失败

c - 根据\n 将字符数组分成多个部分

c - 命名管道和后台进程