将一根管道的输出连接到一个FIFO的输入

时间:2019-01-22 13:54:01

标签: unix pipe client-server fifo

我正在尝试编写一个客户机-服务器程序,其中有三个可执行文件D1,D2和D3,它们提供一些数据作为输出。客户端请求这些数据源中的任何一个,并在常见的fifo的帮助下将其pid发送到服务器。发送此请求的结构是:

int

收到请求后,服务器将打开一个fifo,其路径名是客户端的pid。因此,它可以作为特定于客户的FIFO。

struct Request
{
    char p[10]; // the pid of the client program in string form
    int req; // 1,2,or 3 depending on which one is required D1,D2 or D3
};

现在,假设 req 字段为1。如果这是对D1的第一个请求,则服务器将运行:

mkfifo(pid,O_CREAT|0666);
int fd1 = open(pid,O_WRONLY);

现在我希望我的客户端从D1的管道中读取。D1包含简单的逻辑程序,例如:

FILE* fp = popen("./D1","r");
int fd = fileno(fp); //for getting the file descriptor for the reading end of the pipe connected to D1

我尝试了 dup2(fd,fd1),但是它不起作用。有什么办法可以连接两个文件描述符fd和fd1吗?

此外,如果另一个客户端请求D1,如何将client2的文件描述符连接到fd,以便两个客户端一起接收相同的消息?

1 个答案:

答案 0 :(得分:1)

您可以代替"connecting"两个文件描述符,而将文件描述符发送给客户端,并让客户端读取:

  1. 服务器在UNIX流套接字上侦听。
  2. 客户端连接套接字并发送请求。
  3. 服务器接收到请求,执行popen并获得文件描述符。
  4. 然后,服务器将文件描述符发送到客户端并关闭文件描述符。
  5. 客户端接收文件描述符并从中读取文件直到EOF。

有关使用SCM_RIGHTS在进程之间发送文件描述符的详细信息,请参见man unix(7)


或者,不使用popen

  1. 服务器fork本身。子级执行mkfifo(客户端在请求中传递了文件名),对其进行open写入,并将其stdout重定向到命名管道的文件描述符中。
  2. 孩子exec负责该应用程序。该应用程序将写入stdout,并进入命名管道。
  3. 客户端打开命名管道并读取应用程序的输出。客户端可以在打开管道文件后unlink