zmq
的某些部分没有以可预测的方式表现。
我使用VS2013和zmq 3.2.4。为了不失去'我的pubsub框架中的消息[旁白:我认为这是一个设计缺陷。我应该能够先启动我的订阅者,然后发布者和我应该收到所有消息]我必须将发布者与订阅者la durapub/durasub等同步。我正在使用durasub.cpp和durapub.cpp中的示例zeromq指南。 如果我按原样使用示例,则系统可以正常运行。
如果我现在在durasub.cpp
中的ZMQ_PUSH
附近添加范围括号
{
zmq::socket_t sync (context, ZMQ_PUSH);
sync.connect(syncstr.c_str());
s_send (sync, "sync");
}
系统停止工作。匹配' ZMQ_PULL'信号永远不会达到durapub.cpp中的应用程序级别。
我已经通过C ++包装器来检查来自zmq_close
的返回值,一切都很顺利。就ZMQ而言,它已将消息传递给端点。
希望我做过一些明显愚蠢的事情?
还有更多。
的加入std::this_thread::sleep_for(std::chrono::milliseconds(1));
允许系统(即pub / sub)重新开始工作。所以它显然是一种竞争条件,大概是在收割者的线程中,因为它破坏了套接字。
更多的挖掘。我认为LIBZMQ-179也提到了这个问题。
编辑#2 2014-08-13 03:00 [UTC + 0000]
Publisher.cpp:
#include <zmq.hpp>
#include <zhelpers.hpp>
#include <string>
int main (int argc, char *argv[])
{
zmq::context_t context(1);
std::string bind_point("tcp://*:5555");
std::string sync_bind("tcp://*:5554");
zmq::socket_t sync(context, ZMQ_PULL);
sync.bind(sync_bind.c_str());
// We send updates via this socket
zmq::socket_t publisher(context, ZMQ_PUB);
publisher.bind(bind_point.c_str());
// Wait for synchronization request
std::string tmp = s_recv (sync);
std::cout << "Recieved: " << tmp << std::endl;
int numbytessent = s_send (publisher, "END");
std::cout << numbytessent << "bytes sent" << std::endl;
}
Subscriber.cpp
#include <zmq.hpp>
#include <zhelpers.hpp>
#include <string>
int main (int argc, char *argv[])
{
std::string connectstr("tcp://127.0.0.1:5555");
std::string syncstr("tcp://127.0.0.1:5554");
zmq::context_t context(1);
zmq::socket_t subscriber (context, ZMQ_SUB);
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);
subscriber.connect(connectstr.c_str());
#if ENABLE_PROBLEM
{
#endif ENABLE_PROBLEM
zmq::socket_t sync (context, ZMQ_PUSH);
sync.connect(syncstr.c_str());
s_send (sync, "sync");
#if ENABLE_PROBLEM
}
#endif ENABLE_PROBLEM
while (1)
{
std::cout << "Receiving..." << std::endl;
std::string s = s_recv (subscriber);
std::cout << s << std::endl;
if (s == "END")
{
break;
}
}
}
如果定义ENABLE_PROBLEM
:
如果未定义ENABLE_PROBLEM
:
答案 0 :(得分:1)
编辑#1 2014-08-11:原始帖子已更改,未显示修订版
在充分尊重的情况下,很难分离目标并模拟任何通过/失败测试来验证目标,而不仅仅是上面的三个SLOC。
让我们一步一步地开始。
T.B.D。
编辑后#1 : ZMQ_PUSH
+ ZMQ_PULL
+(隐藏 {{1 <}> + ZMQ_PUB
...下次发布的是ProblemDOMAIN上下文完整的来源,最好的是自我测试用例输出:
ZMQ_SUB
)
T.B.D。
post-EDIT#1 :n.b:ZMQ_LINGER会影响资源的 ...
// <code>-debug-isolation-framing ------------------------------------------------
std::cout << "---[Pre-test]: sync.connect(syncstr.c_str()) argument" << std::endl;
std::cout << syncstr.c_str() << std::endl;
std::cout << "---[Use/exec]: " << std::endl;
sync.connect( syncstr.c_str());
// <code>-debug-isolation-framing ------------------------------------------------
...
,这可能会在ZMQ_Context终止出现之前占用。 (并且可以阻止......伤害......)
此参数在.close()
即将终止时生效,而发送队列尚未清空并且正在尝试Context
处理。
在大多数架构中......(低延迟/高性能,微秒和纳秒计数......),(共享/受限)资源设置/处置操作出现的原因很多 < / strong>在系统生命周期结束时的最开始,或。不用说更多原因,只需想象一下与所有设置/丢弃操作直接相关的开销,这些开销完全不可能发生(重复发生的次数越少......)在近乎真实的日常操作流程中时间系统设计。
因此,让系统进程进入最后的“整理”阶段(就在退出之前)
设置zmq_close()
只会忽略&lt; 发件人&gt; 队列中的任何内容,并允许提示ZMQ_LINGER == 0
+ {{ 1}}
同样地,zmq_close()
会将&lt; 发件人&gt; 的队列中的任何内容置于 [拥有最大价值] ,整个系统必须等待ad-infimum ,之后(希望是任何)&lt; receiver &gt; 检索&amp;在允许任何zmq_term()
+ ZMQ_LINGER == -1
被允许发生之前,“消耗”所有已排队的消息......这可能会很长并完全超出您的控制范围......
最后zmq_close()
作为妥协来等待一定数量的[msec] -s,如果某些&lt; 接收器&gt; 来了并检索一个已列出的消息。但是,在给定的TimeDOMAIN里程碑中,系统会前进到zmq_term()
+ ZMQ_LINGER > 0
以正常清理所有保留资源,并根据系统设计时序约束退出。