簡體   English   中英

Linux:創建簡單的非阻塞服務器和客戶端以通過命名管道進行通信

[英]Linux : Creating a simple non-blocking server and client to communicate over 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移出服務器循環。

您也可以open閱讀,但可以fopen寫作,但是我想這只是一個錯字。 此組合將無法運行。 您需要將fopen的模式更改為"r"

還有其他較小的問題。

  1. 您沒有在客戶端中檢查錯誤。 在您的程序中,客戶端將在大多數時間內無法open ,但有時打開會成功而寫入會失敗。
  2. 在此程序中將stdio用於管道幾乎沒有意義。 readwrite會做就好了。

最后但並非最不重要的一點是, sleep表明存在設計問題。 確實,在該程序中,阻塞I / O更有意義。 如果您只想嘗試非阻塞I / O,則可以使用sleep ,但是在實際程序中應避免使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM