EAGAIN在ZMQ扩展请求回复

时间:2018-04-05 06:26:09

标签: c++ fork ipc zeromq

我正在尝试创建REQ< - >路由器< - >经销商< - >用C ++进行REP通信。子进程绑定路由器和经销商,路由器和经销商之间的代理,将REP连接到经销商并等待带有zmq_recv的消息。

父进程将REQ连接到路由器并尝试发送消息,但是我得到zmq_send error in parent: Resource temporarily unavailableEAGAIN)。根据{{​​3}}文档,EAGAIN表示:

  

请求了非阻止模式,此时无法发送消息。

但是,在子进程中收到消息确实后才会发送消息。为什么它会返回那个errno?

以下是zmq_send

#include <zmq.h>
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <thread>
#include <stdio.h>

int main() {
  char connect_path[35];
  int rc;
  int msg;
  pid_t child_pid = fork();

  if (child_pid == 0) {
    // Child
    void* child_context = zmq_ctx_new ();
    if (child_context == NULL) {
      std::cerr << "\nChild context error\n";
    }

    void* router = zmq_socket(child_context, ZMQ_ROUTER);
    if (router == NULL) {
      perror("zmq_socket of type router error");
    }
    char bind_path[35];

    snprintf(bind_path, sizeof(bind_path), "ipc:///tmp/zmqtest%d-router", getpid());
    rc = zmq_bind(router, bind_path);
    assert (rc == 0);

    void* dealer = zmq_socket(child_context, ZMQ_DEALER);
    if (dealer == NULL) {
      perror("zmq_socket of type dealer error");
    }

    snprintf(bind_path, sizeof(bind_path), "ipc:///tmp/zmqtest%d-dealer", getpid());
    rc = zmq_bind(dealer, bind_path);
    assert (rc == 0);

    std::thread z_proxy (zmq_proxy, router, dealer, nullptr);
    z_proxy.detach();

    void* rep_socket = zmq_socket (child_context, ZMQ_REP);
    if (rep_socket == NULL) {
      perror("zmq_socket of type rep error");
    }

    snprintf(connect_path, sizeof(connect_path), "ipc:///tmp/zmqtest%d-dealer", getpid());
    rc = zmq_connect(rep_socket, connect_path);
    assert (rc == 0);

    while(1) {
      if (zmq_recv (rep_socket, &msg, sizeof(msg), 0) != 0) {
        perror("zmq_recv error");
      }
      printf("\nReceived msg %d in process %d\n", msg, getpid());
      break;
    }
    if (zmq_close(rep_socket) != 0) {
      perror("zmq_close of rep_socket in child error");
    }
    if (zmq_ctx_term(child_context) != 0) {
      perror("zmq_ctx_term of child_context error");
    }
  } else {
    // Parent
    sleep(1);

    void* parent_context = zmq_ctx_new ();
    if (parent_context == NULL) {
      std::cerr << "\nParent ctx error\n";
    }

    void* req_socket = zmq_socket (parent_context, ZMQ_REQ);
    if (req_socket == NULL) {
      perror("zmq_socket of type req error in parent");
    }

    snprintf(connect_path, sizeof(connect_path), "ipc:///tmp/zmqtest%d-router", child_pid);
    rc = zmq_connect(req_socket, connect_path);
    assert (rc == 0);

    msg = 30;
    if (zmq_send (req_socket, &msg, sizeof(msg), 0) != 0) {
      perror("zmq_send error in parent");
    }

    if (zmq_close(req_socket) != 0) {
      perror("zmq_close of req_socket in parent error");
    }
    if (zmq_ctx_term(parent_context) != 0) {
      perror("zmq_ctx_term of parent_context error");
    }
  }
}

1 个答案:

答案 0 :(得分:1)

第1步:进行一项简单的测试:

嗯,作为最低点,首先应该有这种测试排队:

 rc =           zmq_send ( req_socket, "A_TEST_BLOCK", 12, ZMQ_DONTWAIT );
 printf ( "INF: zmq_send ( req_socket, "A_TEST_BLOCK", 12, ZMQ_DONTWAIT )\nZMQ: returned rc == %d\nZMQ: zmq_errno ~ %s\n",
           rc,
           zmq_strerror ( zmq_errno() )
           );

第2步:发布打印输出

接下来,如果有任何“遗漏”镜头,则错误分析可能会就潜在原因提出建议 (当且仅当parent_ctx确实被拒绝甚至接受来自最简单zmq_send()调用它的内部排队设施的数据时,明确原因已完成所以)。

否则我们什么都不知道( ZMQ_DONTWAIT 标志不是这里的原因。)

作为测试was run, it yielded:

  

INF: zmq_send ( req_socket, 'A_TEST_BLOCK', 12, ZMQ_DONTWAIT )
   ZMQ: returned rc == 12
   ZMQ: zmq_errno ~ Resource temporarily unavailable

第3步:

测试证实,根据文件:

  

zmq_send() 函数将返回消息如果成功的字节数。

所以,让我们深入挖掘一下:

int major, minor, patch;

zmq_version ( &major, &minor, &patch );
printf ( "INF: current ØMQ version is %d.%d.%d\nZMQ: zmq_errno ~ %s\n",
          major, minor, patch,
          zmq_strerror ( zmq_errno() )
          );

第4步:

如果最新的API更新不符合已发布的API规范,请记录事件:

printf ( "EXPECT( NO ERROR, ON START ): zmq_errno ~ %s\n",
          zmq_strerror ( zmq_errno() )
          );

printf ( "EXPECT( <major>.<minor>.<patch> ): zmq_version ~\n" );

int major, minor, patch
zmq_version ( &major, &minor, &patch );

printf ( "INF: current ØMQ version is %d.%d.%d\nZMQ: zmq_errno ~ %s\n",
          major, minor, patch
          )

printf ( "EXPECT( NO ERROR ): zmq_errno ~ %s\n",
          zmq_strerror ( zmq_errno() )
          );

printf ( "EXPECT( NO ERROR ): zmq_send() ~ %s\n" );

rc =           zmq_send ( req_socket, "A_TEST_BLOCK", 12, ZMQ_DONTWAIT );
printf ( "INF: zmq_send ( req_socket, "A_TEST_BLOCK", 12, ZMQ_DONTWAIT )\nZMQ: returned rc == %d which ouhgt be == 12, is it?\n",
       rc
       );

printf ( "EXPECT( NO ERROR ): zmq_errno ~ %s\n",
          zmq_strerror ( zmq_errno() )
          );

如果出现意外结果,请随时提出问题。