如何在Linux中"反转"POSIX消息队列?



我正试图找出如何"扭转";一个单一的POSIX消息队列,使客户端和服务器进程之间的双向通信,而只使用一个POSIX消息队列(即一次只有一个内存段)。从本质上讲,这是一种支持双向通信的半双工设置,但消息一次只能在一个方向上流动。

标准方法是为客户端使用一个队列->服务器和一个服务器队列->客户端如下所示(这基本上是我当前的代码)。

客户:

...
int read = mq_open("servertoclient", O_RDWR | O_CREAT, 0600, 0);
int write = mq_open("clienttoserver", O_RDWR | O_CREAT, 0600, 0);
char send_buffer[8192];
mq_send(write, send_buffer, 8192, 0); //send message to server
char receive_buffer[8192];
mq_receive(read, receive_buffer, 8192, 0); //receive response from server
mq_close(write);
mq_close(read);
mq_unlink("servertoclient");
mq_unlink("clienttoserver");
...

服务器:

...
int write = mq_open("servertoclient", O_RDWR | O_CREAT, 0600, 0);
int read = mq_open("clienttoserver", O_RDWR | O_CREAT, 0600, 0);
char send_buffer[8192];
mq_send(write, send_buffer, 8192, 0); //send message to client
char receive_buffer[8192];
mq_receive(read, receive_buffer, 8192, 0); //receive response from client
mq_close(write);
mq_close(read);
mq_unlink("servertoclient");
mq_unlink("clienttoserver");
...

我正在寻找一种方法来完成几乎相同的事情,但一次只使用一个消息队列,而不是每个方向同时使用一个消息队列。唯一的区别是,对于单个队列,不支持同时发送/接收,这在我的情况下是可以的。服务器和客户端将使用某种特殊的"代码"来表示队列反转。这类似于你说话的收音机,然后松开按钮,接收器的收音机就会发出嘟嘟声,让他们知道你已经结束了通话。然后你听接收器的信息,直到你的收音机发出哔哔声。但是发送者和接收者永远不能互相交谈。

下面的内容:

客户:

open a single queue with mq_open for writing to the server
send some data
send a special message notifying the server that the queue is to be reversed
prepare queue for reading (not sure how to do this)
read data from server until the 'reverse' message is received, then revert queue to write
... keep going like this until a terminating message is received or client exits
unlink the queue

服务器:

open a single queue with mq_open for reading from client
read in data
if the terminating message is read, 
prepare queue for writing to client
send data and finish by sending the special 'reverse' message
prepare queue for reading
... keep going like this until a terminating message is received or server exits
unlink the queue

客户端将始终初始化第一条消息,因此永远不会有服务器想要初始发送消息的危险,例如

我不愿意使用任何其他进程间通信方法(如共享内存,sysv队列,管道,tcp/udp等)。

我怕你想要达到的效果不会工作。

POSIX消息队列的基本概念是:
  • 多个应用程序/线程可以打开相同的message_queue
  • 它们都可以将消息写入队列和/或从队列中读取消息
  • 从队列中读取消息是消耗,即一次读取所消耗的消息对于连接到相同message_queue
  • 的任何其他客户端都不再可用。

在使用message_queue的具体设置中,其中恰好连接了2个参与者(一个作为客户端角色,另一个作为服务器角色),您会遇到描述逻辑的以下问题:

当客户端发送了一些消息(将被服务器消耗),然后发送了特殊的消息/令牌,这将表明从现在开始服务器将消息写入队列后,客户端必须决定何时从message_queue中再次读取以检查服务器的回复。现在可能有两种情况:

  1. 客户端已经(幸运地)等待了足够长的时间,服务器已经消耗了之前客户端发送的所有消息。然后客户端将读取新的消息,服务器已经为他放入队列。
  2. 客户端速度太快,在服务器有机会消费之前读取/消费自己的消息。那么整个协议就被破坏了。

底线:由于POSIX消息队列:

  • 有销毁/消耗读取
  • 不提供选择性读取的消息

你想要实现的是不可能的,除非你有一个额外的侧通道来同步客户端/服务器…但这实际上是第二个message_queue,您想要删除它。

最新更新