如何为每个客户端创建一个唯一的命名管道

Posted

技术标签:

【中文标题】如何为每个客户端创建一个唯一的命名管道【英文标题】:How to create an unique Named Pipe for each Client 【发布时间】:2021-06-15 20:14:35 【问题描述】:

我有一个典型的客户端-服务器架构,其中服务器不断地从管道中读取数据以查看是否有客户端发送了某些内容。通常所做的是还有一个命名管道,以便服务器也能够将它需要的任何内容发送给客户端。

我的问题是我需要根据我的需要向特定的客户发送特定的消息。例如,目前,对于客户端 A 和客户端 B,如果客户端 A 通过带有“进程”的管道发送消息,我需要服务器向客户端 A 发送回一个“OK”的回复,但是会发生什么一个随机的得到它(不太确定这里会发生什么,但我假设一旦其中一个客户端读取了管道中的内容,另一个将无法再读取它)。

如何为每个客户端创建一个命名管道,以便服务器可以将特定消息发送到特定客户端?下面是我的代码:

客户端.c


#define FIFO_FILE_1  "../tmp/fifo"
#define FIFO_FILE_2  "../tmp/fifo2"

int main(int argc, char *argv[])

    /*if(mkfifo("fif", 0666) < 0)
        perror("mkfifo");
    */

    int client_to_server; 
    int server_to_client;

    if((client_to_server = open(FIFO_FILE_1, O_WRONLY))<0)
        perror("open fifo");
        exit(1);
    
    
    if((server_to_client = open(FIFO_FILE_2, O_RDONLY))<0)
        perror("open fifo");
        exit(1);
    

    if(argc>2)
      write(client_to_server, "process\n", 9);
    

    int bytes_read = 0;
    char buf[1024]; 

    while(1)
        while((bytes_read = read(server_to_client, buf, 1024)) > 0)
            write(1,"Received",7);
        
    

    close(client_to_server);
    close(server_to_client);
    unlink(FIFO_FILE_1);
    unlink(FIFO_FILE_2);

    return 0;

服务器.c

#define FIFO_FILE_1  "../tmp/fifo"
#define FIFO_FILE_2  "../tmp/fifo2"

int main(int argc, char *argv[])

    // Create named pipes
    if(mkfifo(FIFO_FILE_1, 0666) < 0)
        perror("mkfifo");
    
    if(mkfifo(FIFO_FILE_2, 0666) < 0)
        perror("mkfifo");
    

    int client_to_server; 
    int server_to_client;

    if((client_to_server = open(FIFO_FILE_1, O_RDONLY))<0)
        perror("open fifo");
        exit(1);
    
    
    if((server_to_client = open(FIFO_FILE_2, O_WRONLY))<0)
        perror("open fifo");
        exit(1);
    

    char buf[1024];  
    char bufaux[1024]; 

    while(1)
        int n = readCommand(client_to_server, buf); //Just reads until \n, shouldn't matter for the problem

        if (n<=0)
            continue;

        strcpy(bufaux,buf);

        char * token = first_arg(bufaux); //Returns the token until it hits a space, in this case it will return "process".

        if(strcmp(token,"process")==0)
            write(server_to_client,"OK", 3);              
    

    close(client_to_server);
    close(server_to_client);
    unlink(FIFO_FILE_1);
    unlink(FIFO_FILE_2);
    
    return 0;

还有一些未显示的附加函数,它们仅用于解析来自客户端的管道。假设strcmp(token,"process")==0 永远为真。

我将如何以及何时为每个客户端创建管道?我的想法是在客户端发送第一条消息时发送某种标识符,然后将其用于向同一个客户端写入消息。

显然问题要复杂得多,内存中的数据将被发送到每个特定的客户端,但作为一个例子,我只需要发送一个“OK”。另外,我不能使用套接字。

【问题讨论】:

如果您没有使用 FIFO,请查看 unix 域套接字。 忘记添加我不能使用套接字。谢谢 【参考方案1】:

解决您的问题的一个简单方法是让客户端为返回消息创建管道。

您可以使用进程的 PID 作为名称的一部分,使其在每个进程中都是唯一的。

然后在客户端与服务器的通信中,它总是包含 PID,以便服务器知道将响应写入哪个管道。

【讨论】:

是的,那肯定行得通。一旦我有一些更新,我会尝试更新问题。 @JohnMulaney 通过包括例如从客户端到服务器的消息中的PID,那么服务器可以更容易地区分客户端通信。这不仅有利于将回复发送给正确的客户端,也有利于记录日志或以其他方式将客户端分开。

以上是关于如何为每个客户端创建一个唯一的命名管道的主要内容,如果未能解决你的问题,请参考以下文章

windows命名管道

windows命名管道

我可以拥有多少个命名管道?

Windows进程间通信—命名管道

命名管道如何识别客户端

如何从多个命名管道接收消息?