c - Posix PIPE 上的非阻塞读取和阻塞写入

标签 c client-server posix fifo sigpipe

我正在编写使用 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。

问题在于,即使 PIPE 的另一端没有写入器,非阻塞读打开也总是成功的。 这意味着如果客户端将在 open() 上阻塞,则服务器将执行非阻塞打开(这将解锁客户端),然后 read() 将返回 0,因为此时 PIPE 和 close() 中没有任何内容,然后控制何时会返回到想要在打开的 PIPE 上执行 write() 的客户端,这将导致 SIGPIPE,因为读取器不再可用(服务器已经关闭了管道)。

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

  1. 在客户端使用“tryAgain()”处理 SIGPIPE - 这看起来真的很糟糕,如果我这样做,不能保证它会在任何时候工作 - 这将取决于良好命令处理顺序的可能性...
  2. 继续阅读 PIPE 在服务器中始终打开(打开一次并在连接被认为完成时关闭)——这在我的应用程序架构中很不方便,但当然可以。我想它会解决问题,但我不确定。

这是我的问题:

  1. 这两种方法中的任何一种都是正确的方法吗?
  2. 还有其他方法可以处理这种情况吗?
  3. 您认为第二种解决方案能否正常工作?
  4. 你会选择什么,为什么?

感谢您的每一个回答。

最佳答案

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

客户端将在 open() 时阻塞 <== open 时不会阻塞

使用select或者epoll来判断哪些文件描述符是可读可写的。

然后,只需调用 read 即可。

您将收到客户端关闭管道作为您需要处理的读取事件的通知,如果它已关闭,则不会写入。

http://linux.die.net/man/4/epoll

https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/

关于c - Posix PIPE 上的非阻塞读取和阻塞写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16757439/

相关文章:

java - 如何解决服务器在 TCP 通信上收到的 RTSP 消息的冲突?

c# - 为什么 Java on Server 和 C# on Client 是流行的选择?

Linux, pthreads -- 发送停止条件

c - C标准库和C POSIX库的区别

c - 在 C 中释放分配给哈希表的内存的最快方法

c - 如何在 C 中使用 for 循环创建模式

c - 获取对端IP地址和端口

sockets - 如何在UDP套接字中使用select()从客户端到服务器进行读写

c - 如何在循环中使用管道,我的正确吗?

c - 指针字符函数未第二次运行