简体   繁体   English

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

[英]Non blocking read and blocking write on Posix PIPE

I'm writing Client-Server application using posix FIFO to communicate. 我正在编写使用posix FIFO进行通信的Client-Server应用程序。 Both client and server are single thread and single process application. 客户端和服务器都是单线程和单进程应用程序。

The server is design to handle multiple clients. 服务器设计用于处理多个客户端。 Each client has own pair of named pipe, one to send messages from Server to this Client and the other to send messages from Client to the Server. 每个客户端都有自己的一对命名管道,一个用于从服务器向此客户端发送消息,另一个用于从客户端向服务器发送消息。

The idea is quite simple, Server loops through all Client to Server pipes and check if there is something to read there. 这个想法很简单,Server循环遍历所有客户端到服务器管道,并检查是否有东西可以在那里阅读。

My first implemenentation was sth like: 我的第一个实现是......

/* 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

As far as I know this code is invalid. 据我所知,这段代码无效。

There are race conditions and for example an order of calls like: 1, 2, 4, 3, 5, 6 - will probably cause SIGPIPE. 有竞争条件,例如:1,2,3,3,5,6的调用顺序 - 可能会导致SIGPIPE。

The problem is that nonblocking read open is always successful even if there is no writer on the other side of PIPE. 问题是即使PIPE的另一侧没有写入器,非阻塞读取打开也总是成功的。 That means that if Client will block on open() then server do nonblocking open (which will unlock Client) and then read() which will return 0 because at the moment nothing will be in PIPE and close() afterwards, then when control will go back to client which want to do write() on opened PIPE it will cause SIGPIPE as the reader is no longer available (server already closed the pipe). 这意味着如果客户端将阻塞open()然后服务器执行非阻塞打开(这将解锁客户端)然后读取()将返回0,因为此时PIPE中没有任何内容,之后将关闭(),然后当控制将回到想要在打开的PIPE上执行write()的客户端,它将导致SIGPIPE,因为读取器不再可用(服务器已经关闭了管道)。

For now i see two solutions: 现在我看到两个解决方案:

  1. Handle SIGPIPE in Client with "tryAgain()" - this looks really bad, if i do such thing there is no guarantee that it will work at any moment - it will depend on possibility of good command processing order... 使用“tryAgain()”在客户端处理SIGPIPE - 这看起来非常糟糕,如果我做这样的事情,不能保证它随时可以工作 - 它将取决于良好的命令处理顺序的可能性......
  2. Keep reading PIPE open all the time in Server (open it once and close when connection will be considered finished) - it is inconvenient in my application architecture but of course possible. 继续阅读PIPE在服务器中一直打开(打开一次并在连接被认为完成时关闭) - 这在我的应用程序架构中是不方便的,但当然可能。 I guess it will fix the problem but I'm not sure about that. 我想这会解决问题,但我不确定。

Here are my questions: 这是我的问题:

  1. Is any of those two approaches correct way to do that? 这两种方法中的任何一种都是正确的方法吗?
  2. Is there any other way to handle that scenario? 有没有其他方法来处理这种情况?
  3. Do you think second solution will work correctly? 你认为第二种解决方案能正常工作吗?
  4. What would you choose and why? 你会选择什么?为什么?

Thanks for every answer. 谢谢你的每一个答案。

I'm having a lot of trouble understanding your question. 我在理解你的问题时遇到了很多麻烦。 Things 事情

Client will block on open() <== nothing blocks on open 客户端将阻止open()<==打开时没有任何块

Use select or epoll to determine which file descriptors are readable and writeable. 使用select或epoll确定哪些文件描述符是可读写的。

Then, just call read on those. 然后,只需调用那些读取。

You will be notified that the client closed the pipe as a read event you'll need to handle and not write if it is closed. 您将收到通知,客户端将管道关闭为您需要处理的读取事件,如果关闭则不会写入。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM