Linux:创建一个简单的非阻塞服务器和客户端,通过命名管道进行通信

时间:2016-05-29 09:43:25

标签: 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存在于文件系统上,必须由客户端使用。

1 个答案:

答案 0 :(得分:0)

主要问题是在循环中打开和关闭文件。这毫无意义。打开和关闭之间的时间间隔非常短,您的客户必须点击它。它几乎没有机会这样做。 &#34;没有这样的设备或地址&#34;消息恰好发生,因为客户端错过文件打开时的瞬间。这是主要问题。尝试将openfopenfclose移出服务器循环。

您还open阅读但fopen写作,但我认为这只是一个错字。这种组合不会运行。您需要将fopen的模式更改为"r"

还有其他较小的问题。

  1. 您没有检查客户端中的错误。在您的程序中,客户端大部分时间都不会open,但有时打开会成功,写入将失败。
  2. 在此程序中使用stdio作为管道是没有意义的。 readwrite会很好。
  3. 最后但同样重要的是,sleep表示设计问题。实际上,在这个程序中阻塞I / O会更有意义。如果您只想尝试非阻塞I / O,可以使用sleep,但在实际程序中应该避免使用。