I wanted to flag the following issue:

Platform: win64 / debug, using visual studio 2010 compiler
Language: C++
ZMQ version: 3.1.0

Description:

A router socket and dealer socket, in separate apps, enjoy a good TCP 
connection and are sending/receiving messages directly. The messages being sent 
from the dealer to the router do not have an empty first frame.

The application using the router socket is killed, then brought back up.

An assertion is generated (in std lib xtree).

When the dealer sends msgs with an empty first-frame this problem does not 
occur.

It appears that during a reconnection, the ROUTER socket relies on there being 
an empty frame. Further anecdotal evidence of this comes from the fact that 
when the dealer socket is configured to send every message with an empty-frame, 
recv()s is done on the router socket fail to provide an empty frame for the 
first message received after a reconnection with the dealer.

It may be that empty frames are mandated when communicating directly to a 
ROUTER socket. If this is the case can this please be documented.

Another interesting quirk:

In this dealer reconnecting with router scenario, the dealer would usually 
receive one unexpected message with a single empty frame from the router after 
a reconnection.

Example code:

This is experimental code I wrote to try reproducing and debugging the 
assertion. By passing in the 'server' command line arg it will run as a server, 
with router socket, if 'client' argument then as a client with a dealer

#include <zmq.hpp>
#include <string>
#include <memory>
#include <iostream>

int main(int argc, char ** argv)
{
    if (argc >= 2)
    {
        zmq::context_t context(1);
        if (strcmp(argv[1], "server") == 0)
        {
            zmq::socket_t serverSock(context, ZMQ_XREP);
            serverSock.bind("tcp://*:6010");

            // record the uuid at first contact (a hack admittedly - hope the 
client never restarts)
            zmq::message_t message;
            serverSock.recv( &message, 0 );
            std::string client_uuid ( static_cast<char*>( message.data()), 
message.size() );

            int msg_count = 0;
            while (1)
            {
                // print out any message we received as a string
                zmq::message_t recvdMsg;
                serverSock.recv( & recvdMsg, 0 );
                std::string msg ( static_cast<char*>( 
recvdMsg.data()),recvdMsg.size() );
                std::cout << "Recv: " << msg << std::endl;

                // for every three frames received, send a reply
                msg_count++;
                if (msg_count % 3 == 0)
                {
                                // send uuid frame
                                zmq::message_t msgToSnd(client_uuid.size()) ;
                    
memcpy(msgToSnd.data(),client_uuid.data(),client_uuid.size());
                    serverSock.send(msgToSnd, ZMQ_SNDMORE);

                    // send reply body
                    std::string body("hello");
                                zmq::message_t msgToSnd2(body.size()) ;
                    memcpy(msgToSnd2.data(),body.data(),body.size());
                    serverSock.send(msgToSnd2, 0);
                }
            }
        }
        else if (strcmp(argv[1], "client") == 0)
        {
            zmq::socket_t clientSock(context, ZMQ_XREQ);
            clientSock.connect("tcp://localhost:6010");
            while (1)
            {
                Sleep(1000);

                /* Uncomment this block to make it is so server can reconnect 
without an assert failing

                // Send an empty frame
                zmq::message_t emptyMsg;
                clientSock.send(emptyMsg, ZMQ_SNDMORE);

                */

                //Send request body
                std::string request("Hello!");
                zmq::message_t msgToSnd(request.size()) ;
                memcpy(msgToSnd.data(),request.data(),request.size());
                clientSock.send(msgToSnd, 0);

                //Check if we've received any replies
                zmq::message_t recvdMsg;
                if (clientSock.recv( & recvdMsg, ZMQ_DONTWAIT ))
                {
                    std::string msg ( static_cast<char*>( 
recvdMsg.data()),recvdMsg.size() );
                    std::cout << "Recv: " << msg << std::endl;
                }
            }
        }
    }
}

Kind regards,

Andrew Bott
_______________________________________________
zeromq-dev mailing list
[email protected]
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to