I put together the following program to show the issue. It seems if the option 
ZMQ_IPV4ONLY is set to 0 (to enable IPV6), then ZMQ as running on OS X allows 
two sockets to bind to the same port, provided the address used is 0.0.0.0. For 
instance, as in the test program, I can construct two sockets, both bound to 
“tcp://0.0.0.0:9998”, as long as ZMQ_IPV4ONLY is set to 0. If the option is set 
to 1, or the test program is run in Linux, centos65…. then things work as 
expected.

Uname of ‘broken’ OS X system:
Darwin khenrick.ddns.nominum.com<http://khenrick.ddns.nominum.com> 14.0.0 
Darwin Kernel Version 14.0.0: Fri Sep 19 00:26:44 PDT 2014; 
root:xnu-2782.1.97~2/RELEASE_X86_64 x86_64

Uname of ‘working’ Linux system:
Linux vagrant-centos65 2.6.32-431.5.1.el6.x86_64 #1 SMP Wed Feb 12 00:41:43 UTC 
2014 x86_64 x86_64 x86_64 GNU/Linux

#include <iostream>
#include <random>
#include <zmq.hpp>

using namespace std;

static const char *DEFAULT_ADDR = "tcp://0.0.0.0:9998";

/*----------------------------------------------------------------------
 * ROUTER socket
 *----------------------------------------------------------------------*/
zmq::socket_t *init_socket(zmq::context_t &context, std::string address, int 
v4only) {
zmq::socket_t *socket_ptr = new zmq::socket_t(context, ZMQ_ROUTER);
cout << "Binding router socket..." << endl;

socket_ptr->setsockopt(ZMQ_IDENTITY, address.data(), address.size());

    int timeout(0);
    socket_ptr->setsockopt(ZMQ_RCVTIMEO, &timeout, sizeof(timeout));
    socket_ptr->setsockopt(ZMQ_SNDTIMEO, &timeout, sizeof(timeout));
    socket_ptr->setsockopt(ZMQ_IPV4ONLY, &v4only, sizeof(v4only));

socket_ptr->bind(address.c_str());

    return socket_ptr;
}

void test_two_socks(int v4only) {
    zmq::context_t ctx;


    zmq::socket_t *zmq_ptr_a = init_socket(ctx, DEFAULT_ADDR, v4only);
    zmq::socket_t *zmq_ptr_b = init_socket(ctx, DEFAULT_ADDR, v4only);

    if (zmq_ptr_a != nullptr) {
        cout << "Bye A!" << endl;
        delete(zmq_ptr_a);
    }

    if (zmq_ptr_b != nullptr) {
        cout << "Bye B!" << endl;
        delete(zmq_ptr_b);
    }
}

/***********************************************************************
 * Main entry point.
 ***********************************************************************/
int
main (int argc, char ** argv)
{
    std::cout << "This succeeds" << std::endl;
    test_two_socks(0);

    std::cout << "This fails" << std::endl;
    test_two_socks(1);

    return 0;
}

_______________________________________________
zeromq-dev mailing list
zeromq-dev@lists.zeromq.org
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to