在使用brew安装zmq和czmq之后,我尝试编译并播放Asynchronous-Majordomo-Pattern,但它不起作用,因为它需要czmq v3。据我所知,我尝试使用 zactor
将其更新为v4,因为
zthread
已弃用,以支持zactor
http://czmq.zeromq.org/czmq3-0:zthread
所以现在以下代码对我来说看起来更新async-majordomo模式,但是它不能按预期工作,当我通过终端运行时它不会创建任何线程。
// Round-trip demonstrator
// While this example runs in a single process, that is just to make
// it easier to start and stop the example. The client task signals to
// main when it's ready.
#include "czmq.h"
#include <stdlib.h>
void dbg_write_in_file(char * txt, int nb_request) {
FILE * pFile;
pFile = fopen ("myfile.txt","a");
if (pFile!=NULL)
{
fputs (txt, pFile);
char str_nb_request[12];
sprintf(str_nb_request, "%d", nb_request);
fputs (str_nb_request, pFile);
fputs ("\n", pFile);
fclose (pFile);
}
}
static void
client_task (zsock_t *pipe, void *args)
{
zsock_t *client = zsock_new (ZMQ_DEALER);
zsock_connect (client, "tcp://localhost:5555");
printf ("Setting up test...\n");
zclock_sleep (100);
printf("child 1: parent: %i\n\n", getppid());
printf("child 1: my pid: %i\n\n", getpid());
int requests;
int64_t start;
printf ("Synchronous round-trip test...\n");
start = zclock_time ();
for (requests = 0; requests < 10000; requests++) {
zstr_send (client, "hello");
// stuck here /!\
char *reply = zstr_recv (client);
zstr_free (&reply);
// check if it does something
dbg_write_in_file("sync round-trip requests : ", requests);
// end check
}
printf (" %d calls/second\n",
(1000 * 10000) / (int) (zclock_time () - start));
printf ("Asynchronous round-trip test...\n");
start = zclock_time ();
for (requests = 0; requests < 100000; requests++) {
zstr_send (client, "hello");
// check if it does something
dbg_write_in_file("async round-trip send requests : ", requests);
// end check
}
for (requests = 0; requests < 100000; requests++) {
char *reply = zstr_recv (client);
zstr_free (&reply);
// check if it does something
dbg_write_in_file("async round-trip rec requests : ", requests);
// end check
}
printf (" %d calls/second\n",
(1000 * 100000) / (int) (zclock_time () - start));
zstr_send (pipe, "done");
}
// Here is the worker task. All it does is receive a message, and
// bounce it back the way it came:
static void
worker_task (zsock_t *pipe, void *args)
{
printf("child 2: parent: %i\n\n", getppid());
printf("child 2: my pid: %i\n\n", getpid());
zsock_t *worker = zsock_new (ZMQ_DEALER);
zsock_connect (worker, "tcp://localhost:5556");
while (true) {
zmsg_t *msg = zmsg_recv (worker);
zmsg_send (&msg, worker);
}
zsock_destroy (&worker);
}
// Here is the broker task. It uses the zmq_proxy function to switch
// messages between frontend and backend:
static void
broker_task (zsock_t *pipe, void *args)
{
printf("child 3: parent: %i\n\n", getppid());
printf("child 3: my pid: %i\n\n", getpid());
// Prepare our sockets
zsock_t *frontend = zsock_new (ZMQ_DEALER);
zsock_bind (frontend, "tcp://localhost:5555");
zsock_t *backend = zsock_new (ZMQ_DEALER);
zsock_bind (backend, "tcp://localhost:5556");
zmq_proxy (frontend, backend, NULL);
zsock_destroy (&frontend);
zsock_destroy (&backend);
}
// Finally, here's the main task, which starts the client, worker, and
// broker, and then runs until the client signals it to stop:
int main (void)
{
// Create threads
zactor_t *client = zactor_new (client_task, NULL);
assert (client);
zactor_t *worker = zactor_new (worker_task, NULL);
assert (worker);
zactor_t *broker = zactor_new (broker_task, NULL);
assert (broker);
// Wait for signal on client pipe
char *signal = zstr_recv (client);
zstr_free (&signal);
zactor_destroy (&client);
zactor_destroy (&worker);
zactor_destroy (&broker);
return 0;
}
当我运行它时,程序似乎停留在评论
//卡在这里/!\
然后当我因为它没有完成而杀死它或打印任何东西时,我需要按下五次 Ctrl + C (^ C)。只有这样,它在控制台上看起来更加冗长,就像它确实在运行一样。
=&GT;请注意,我删除了所有printf()
步骤的输出,因为阅读时非常麻烦。
运行时,只有在发送了五个 Ctrl + C 之后,它才会向 dbg_write_in_file()
函数调用该文件中写入任何内容(^ C)。
客户端工作人员和代理人任务都返回与程序本身相同的getppid
号码(我的终端)和getpid
。
我使用gcc trippingv4.c -o trippingv4 -L/usr/local/lib -lzmq -lczmq
进行编译。
当我试图杀死它时:
./trippingv4
Setting up test...
child 1: parent: 60967
child 1: my pid: 76853
Synchronous round-trip test...
^Cchild 2: parent: 60967
child 2: my pid: 76853
^Cchild 3: parent: 60967
child 3: my pid: 76853
^C^C^CE: 18-02-28 00:16:37 [76853]dangling 'PAIR' socket created at src/zsys.c:471
E: 18-02-28 00:16:37 [76853]dangling 'DEALER' socket created at trippingv4.c:29
E: 18-02-28 00:16:37 [76853]dangling 'PAIR' socket created at src/zsys.c:471
E: 18-02-28 00:16:37 [76853]dangling 'DEALER' socket created at trippingv4.c:89
更新
感谢您详细解答@ user3666197。在第一部分中,编译器不编译断言调用,因此我只是显示值而是直观地进行比较,它们是相同的。
int czmqMAJOR,
czmqMINOR,
czmqPATCH;
zsys_version ( &czmqMAJOR, &czmqMINOR, &czmqPATCH );
printf( "INF: detected CZMQ ( %d, %d, %d ) -version\n",
czmqMAJOR,
czmqMINOR,
czmqPATCH
);
printf( "INF: CZMQ_VERSION_MAJOR %d, CZMQ_VERSION_MINOR %d, CZMQ_VERSION_PATCH %d\n",
CZMQ_VERSION_MAJOR,
CZMQ_VERSION_MINOR,
CZMQ_VERSION_PATCH
);
输出:
INF: detected CZMQ ( 4, 1, 0 ) -version
INF: CZMQ_VERSION_MAJOR 4, CZMQ_VERSION_MINOR 1, CZMQ_VERSION_PATCH 0
zsys_info调用确实编译但在终端上没有显示任何内容,即使使用fflush(stdout)
以防万一,我只使用了printf
:
INF: This system's Context() limit is 65535 ZeroMQ socketsINF: current state of the global Context()-instance has:
( 1 )-IO-threads ready
( 1 )-ZMQ_BLOCKY state
然后我用zsys_set_io_threads(2)
和/或zmq_ctx_set (aGlobalCONTEXT, ZMQ_BLOCKY, false);
更改了全局上下文线程值,仍然被阻止。看起来zactor不适用于系统线程,因为zthread是...或者没有给出类似的行为。鉴于我在zeromq(也是零)的经验,我可能会尝试一些无法实现的东西。
更新已解决但未正确
我的主要错误是没有正确启动zactor实例
一个actor函数必须在初始化时调用zsock_signal(pipe)并且必须监听管道并退出$ TERM命令。
并且在调用zactor_destroy (&proxy);
我让下面的最终代码,但你仍然需要在 Ctrl + C 的最后退出,因为我没弄清楚如何管理{{1}信号正确。此外,zactor似乎仍然没有使用系统theads。它可能是这样的设计,但我不知道它是如何在木材背后起作用的。
$TERM
答案 0 :(得分:1)
int czmqMAJOR,
czmqMINOR,
czmqPATCH;
zsys_version ( &czmqMAJOR, &czmqMINOR, &czmqPATCH );
printf( "INF: detected CZMQ( %d, %d, %d )-version",
czmqMAJOR,
czmqMINOR,
czmqPATCH
);
assert ( czmqMAJOR == CZMQ_VERSION_MAJOR & "Major: does not match\n" );
assert ( czmqMINOR == CZMQ_VERSION_MINOR & "Minor: does not match\n" );
assert ( czmqPATCH == CZMQ_VERSION_PATCH & "Patch: does not match\n" );
如果这符合您的期望,您可能希望DLL版本在正确的位置匹配并找到。
可以测试整个马戏团以非阻塞模式运行,以证明,没有其他阻止程序,但作为简要检查,我还没有在CZMQ-API中发现这样的选项,本机API允许标记一个NOBLOCK
操作上的 { _send() | _recv() }-
选项会阻止它们被阻止(在DEALER
的情况下_send()
套接字实例可能就是这种情况 - s,当还没有任何具有POSACK-ed .bind()/.connect()
状态的交易对手时。
在这里,我没有找到一些工具,可以像在原生API中那样快速地执行此操作。也许你会有更多的运气来完成这个。
Context()
实例的存在(如果已准备好):在第一次套接字实例化之前添加,以确保我们在任何和所有套接字生成之前及其各自的_bind()/_connect()
操作之前使用以下自我报告行:
zsys_info ( "INF: This system's Context() limit is %zu ZeroMQ sockets",
zsys_socket_limit ()
);
Context()
实例化:以确保全局Context()实例已启动并运行,在任何更高抽象的实例之前询问是否实现其他内部性(套接字,计数器,处理程序,端口管理等)
// Initialize CZMQ zsys layer; this happens automatically when you create
// a socket or an actor; however this call lets you force initialization
// earlier, so e.g. logging is properly set-up before you start working.
// Not threadsafe, so call only from main thread. Safe to call multiple
// times. Returns global CZMQ context.
CZMQ_EXPORT void *
zsys_init (void);
// Optionally shut down the CZMQ zsys layer; this normally happens automatically
// when the process exits; however this call lets you force a shutdown
// earlier, avoiding any potential problems with atexit() ordering, especially
// with Windows dlls.
CZMQ_EXPORT void
zsys_shutdown (void);
并且可能更好地调整IO性能,在初始化状态下使用此权限:
// Configure the number of I/O threads that ZeroMQ will use. A good
// rule of thumb is one thread per gigabit of traffic in or out. The
// default is 1, sufficient for most applications. If the environment
// variable ZSYS_IO_THREADS is defined, that provides the default.
// Note that this method is valid only before any socket is created.
CZMQ_EXPORT void
zsys_set_io_threads (size_t io_threads);
这个手动实例化提供了一个额外的好处,从具有实例句柄void指针,以便可以通过 zmq_ctx_get()
工具检查它的当前状态和形状:
void *aGlobalCONTEXT = zsys_init();
printf( "INF: current state of the global Context()-instance has:\n" );
printf( " ( %d )-IO-threads ready\n", zmq_ctx_get( aGlobalCONTEXT,
ZMQ_IO_THREADS
)
);
printf( " ( %d )-ZMQ_BLOCKY state\n", zmq_ctx_get( aGlobalCONTEXT,
ZMQ_BLOCKY
)
); // may generate -1 in case DLL is << 4.2+
...
// Set interrupt handler; this saves the default handlers so that a
// zsys_handler_reset () can restore them. If you call this multiple times
// then the last handler will take affect. If handler_fn is NULL, disables
// default SIGINT/SIGTERM handling in CZMQ.
CZMQ_EXPORT void
zsys_handler_set (zsys_handler_fn *handler_fn);
,其中
// Callback for interrupt signal handler
typedef void (zsys_handler_fn) (int signal_value);