Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Posix管道上的非阻塞读取和阻塞写入_C_Client Server_Posix_Fifo_Sigpipe - Fatal编程技术网

C Posix管道上的非阻塞读取和阻塞写入

C Posix管道上的非阻塞读取和阻塞写入,c,client-server,posix,fifo,sigpipe,C,Client Server,Posix,Fifo,Sigpipe,我正在使用posix FIFO编写客户机-服务器应用程序进行通信。客户端和服务器都是单线程和单进程应用程序 服务器设计为处理多个客户端。每个客户端都有自己的一对命名管道,一个用于将消息从服务器发送到此客户端,另一个用于将消息从客户端发送到服务器 这个想法很简单,服务器通过所有客户端到服务器的管道循环,并检查那里是否有可以读取的内容 我的第一个想法是: /* SERVER */ int desc = open(pipeName, O_RDONLY | O_NDELAY); //1 assert(d

我正在使用posix FIFO编写客户机-服务器应用程序进行通信。客户端和服务器都是单线程和单进程应用程序

服务器设计为处理多个客户端。每个客户端都有自己的一对命名管道,一个用于将消息从服务器发送到此客户端,另一个用于将消息从客户端发送到服务器

这个想法很简单,服务器通过所有客户端到服务器的管道循环,并检查那里是否有可以读取的内容

我的第一个想法是:

/* SERVER */
int desc = open(pipeName, O_RDONLY | O_NDELAY); //1
assert(desc > 0); //just simplyfing error handling
int read = read(desc, buffer, BUFSIZE); //2
if(read > 0)
  do_stuff();
close(desc); //3

/* CLIENT */
int desc = open(pipeName, O_WRONLY) //4
assert(desc > 0); //just simplyfing error handling
int read = write(desc, buffer, BUFSIZE) //5
close(desc); //6
据我所知,这个代码是无效的

存在竞争条件,例如,调用的顺序,如:1、2、4、3、5、6-可能会导致SIGPIPE

问题是,即使管道的另一端没有写入程序,非阻塞读打开总是成功的。 这意味着,如果客户机将在open()上阻塞,那么服务器将执行非阻塞打开(这将解锁客户机),然后执行read(),这将返回0,因为此时管道中没有任何内容,随后将关闭(),然后当控件返回到要执行write()的客户机时在打开的管道上,由于读卡器不再可用(服务器已关闭管道),它将导致SIGPIPE

目前我看到两种解决方案:

  • 使用“tryAgain()”在客户端处理SIGPIPE-这看起来非常糟糕,如果我做了这样的事情,就不能保证它在任何时候都能工作-这将取决于良好的命令处理顺序的可能性
  • 在服务器中始终保持阅读管道打开(打开一次,在连接完成时关闭)——这在我的应用程序架构中很不方便,但当然是可能的。我想它会解决问题,但我不确定
  • 以下是我的问题:

  • 这两种方法中有哪一种是正确的方法
  • 有没有其他方法来处理这种情况
  • 你认为第二种解决方案正确吗
  • 你会选择什么?为什么

  • 谢谢你的回答。

    我很难理解你的问题。事物


    客户端将在open()OT上阻塞:它应该是
    assert(desc!=-1)
    断言(desc>=0)
    as
    open()
    错误时返回
    -1
    ,成功时返回非负整数。不要编辑问题/代码。评论或回答它的错误。当你说它应该处理多个客户时,你的意思是同时处理吗?因为您的代码一次只处理一个。处理sigpipe或“在服务器中始终打开读取管道”的任何更改都不会使它同时处理多个连接。当然,不是同时处理,但我希望它能给人留下这样的印象。我的意思是-它可以循环通过所有客户机,并始终处理一个已经准备好尽快。并为编辑抱歉。你说得对。服务器可以轮询以找到哪个客户端想要写入某些内容,这可能会起到某种作用(我的意思是,它会发现客户端正在打开一些管道进行写入,并等待读卡器开始写入这些管道)。但我不确定这是否会改变问题。不过,若服务器发现有一个客户端想要写一些东西,它将打开,然后使用NODELAY标志读取,这将导致它读取0字节,然后关闭(服务器不能等待数据,因为它只有一个线程!)。这意味着客户端将有sam问题-其打开指令将被解锁,但当进程达到写入时,另一侧将没有读卡器(已关闭),这将导致SIGPIPE。或者我错了?你错了,因为如果你正确地进行了轮询,你会收到通知,对方已经终止了连接,这样你就可以知道不要对其调用write。嗯,那么我今天将尝试以这种方式实现它。我想在我的C++ OO代码中可能会出现系统通知处理的问题,但我猜没有什么不可能处理的——它看起来非常糟糕;谢谢你的回答。