【问题标题】:C/Linux - Server <-> Terminal communication with named pipesC/Linux - 服务器 <-> 与命名管道的终端通信
【发布时间】:2017-04-16 20:43:25
【问题描述】:

我正在为大学做一个项目,我只能使用命名管道 (mkfifo()) 来建立服务器和终端(都是我创建的)之间的通信。

有:

  • 只有 1 台服务器;
  • 1 个或多个终端;

实际上我的应用程序是这样工作的:

  • 终端通过命名管道(红色)向服务器发送一个command_t结构。这个命名管道是一个 FIFO,它在所有终端之间共享。发送 command_t 结构后,终端将尝试从另一个命名管道(蓝色)读取回复,并且它将被阻止,直到服务器在该管道中写入内容。
  • 服务器从命名管道(红色)读取并按照先到先得的原则处理接收到的命令(command_t 结构)。 有多个线程,意味着同时处理多个请求。
  • 处理完命令后,服务器通过另一个命名管道(蓝色)发送一个reply_t结构。

问题:

如果我只用一个线程启动服务器,这一切都很好,因为响应 (reply_t) 是按照命令到达的顺序发送的 (command_t)

但是如果我用多个线程启动服务器,我不能保证响应以命令到达的相同顺序发送,这将使我有混合响应(例如,我将在终端上收到1 终端 2 等命令的执行结果...)。

我正在考虑制作这样的东西:

在此解决方案中,我将为连接到服务器的每个终端提供一个输出 PIPE,而不是在所有终端之间共享一个输出 PIPE。但是如何在 C 中实现可变数量的终端呢?我什至无法检测到新终端何时打开输入管道。

有什么建议吗? 谢谢!

【问题讨论】:

  • 即使服务器只有一个线程,考虑到多个终端都可以读取fifo,如何确保正确的终端得到响应?
  • @kaylum 它可以工作,因为如果终端 A 发送命令,那么它将被 read() 函数阻塞,直到服务器写回一些东西。如果 A 和 B 发送命令,则最先发送命令的人将首先被 read() 函数阻塞。所以当服务器写入响应时,终端 A 将首先读取,然后是终端 B。
  • 事情并非如此。仅仅因为一个进程首先调用 read 并不能确保它会首先被唤醒。无论如何,您无法确保在写入之后和读取之前没有暂停进程。多进程/线程很难。毫无疑问,您会发现许多可能的比赛条件。
  • @kaylum 它在多线程中失败,因为我可以从终端 A 发送一个命令,从终端 B 发送一个命令。但是如果服务器首先执行 B,它会将命令 B 的回复发送到终端A(在 read() 函数上被阻塞)
  • 您是否希望同时处理数千个终端?如果没有,那么链表就可以了。或者如果你真的想优化然后实现你自己的哈希表 - 这一点都不难。或者,每次只打开/写入/关闭。

标签: c linux multithreading bash


【解决方案1】:

丹尼尔,

我之前实现了一个类似的服务器,你可以监听一个终端,当终端完成消息时,你可以分叉进程并将响应发送回子进程,而在循环中的父进程中创建另一个监听器对于下一个终端,正如 ccarton 所说:

类似这样的:

while (1)
 {
   newsockfd = accept(sockfd,
               (struct sockaddr *) &cli_addr, &clilen);
   if (newsockfd < 0)
     error("ERROR on accept");
   pid = fork();
   if (pid < 0)
     error("ERROR on fork");
   if (pid == 0)
   {
     close(sockfd);
     dostuff(newsockfd);
     exit(0);
   }
   else
     close(newsockfd);
 } /* end of while */

你可以在这里找到完整的解释: http://www.linuxhowtos.org/C_C++/socket.htm

在“服务器代码的增强”部分下。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    将服务器与终端同步的一种方法是使用System V semaphore。在开始“收听”频道“x”分钟之前,终端会获取信号量。如果消息到达,终端处理它并发送回响应,否则,如果发生超时,它只是释放信号量,以便其他终端可以开始监听。这样做的问题是您失去了并行处理多个消息的能力。

    另一种方法是 @Moulin 所说,在您的结构 command_treply_t 中使用 id(例如 fork() 返回的 PID)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多