Skip to content

Connecting a socket to an address using 0.0.0.0 fails without an exception under Windows #527

@CDixon0416

Description

@CDixon0416

During a port of a project from Centos 7 to Windows 10, I discovered some inconsistent behavior when connecting to a socket using a wildcard address and port. In the client code I manually connected to the port provided by the server code using 0.0.0.0 and no communication occurs, change the string to using localhost and the sockets communicate as expected.

This seems to be a problem that was already seen in libzmq zeromq/libzmq#1920 and persists in cppzmq or at least in version 4.7.1 provided by vcpkg. While its not a huge problem it does mean windows code is required to parse out the port from socket.get(zmq::sockopt::last_endpoint) and change the connection string to use localhost or 127.0.0.1 with out any indicator of what the problem is.

Modified Client and Server code to replicate behavior:

//
//  Hello World client in C++
//  Connects REQ socket to tcp://localhost:5555
//  Sends "Hello" to server, expects "World" back
//
#include <zmq.hpp>
#include <string>
#include <iostream>

int main ()
{
    //  Prepare our context and socket
    zmq::context_t context (1);
    zmq::socket_t socket (context, zmq::socket_type::req);

    std::cout << "Connecting to hello world server..." << std::endl;
    // Manually change address to port provided by server
    socket.connect ("tcp://0.0.0.0:59474");

    //  Do 10 requests, waiting each time for a response
    for (int request_nbr = 0; request_nbr != 10; request_nbr++) {
        zmq::message_t request (5);
        memcpy (request.data (), "Hello", 5);
        std::cout << "Sending Hello " << request_nbr << "..." << std::endl;
        socket.send (request, zmq::send_flags::none);

        //  Get the reply.
        zmq::message_t reply;
        socket.recv (reply, zmq::recv_flags::none);
        std::cout << "Received World " << request_nbr << std::endl;
    }
    return 0;
}
//
//  Hello World server in C++
//  Binds REP socket to tcp://*:5555
//  Expects "Hello" from client, replies with "World"
//
#include <zmq.hpp>
#include <string>
#include <iostream>
#ifndef _WIN32
#include <unistd.h>
#else
#include <windows.h>

#define sleep(n)	Sleep(n)
#endif

int main () {
    //  Prepare our context and socket
    zmq::context_t context (2);
    zmq::socket_t socket (context, zmq::socket_type::rep);
    socket.bind ("tcp://*:*");

    while (true) {
        zmq::message_t request;
       
        // Print out actual address for client to use
        std::cout << socket.get(zmq::sockopt::last_endpoint) << std::endl;
        
        //  Wait for next request from client
        socket.recv (request, zmq::recv_flags::none);
        std::cout << "Received Hello" << std::endl;

        //  Do some 'work'
        sleep(1);

        //  Send reply back to client
        zmq::message_t reply (5);
        memcpy (reply.data (), "World", 5);
        socket.send (reply, zmq::send_flags::none);
    }
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions