[zeromq-dev] Empty message does not close ZMQ_STREAM socket?

Auer, Jens jens.auer at cgi.com
Mon Mar 21 17:06:43 CET 2016


Hi,

I tried that before and thought that sending the close message repetitively would do the trick. To better see if the socket is really closed, I set the reconnect interval to ten minutes in the client by setting
    int tenminutes = 60000;
    client.setsockopt(ZMQ_RECONNECT_IVL, &tenminutes, sizeof(tenminutes));

Now, when I use the following server which is basically taken from the manpage, I can close the socket by sending the close message twice. Removing the ZMQ_SNDMORE flag does not change anything.

int main(int argc, char* argv[]) {
        int n = std::atoi(argv[1]);
    void *ctx = zmq_ctx_new ();
    /* Create ZMQ_STREAM socket */
    void *socket = zmq_socket (ctx, ZMQ_STREAM);

    int rc = zmq_bind (socket, "tcp://127.0.0.1:5000");
    /* Data structure to hold the ZMQ_STREAM ID */
    uint8_t id [256];
    size_t id_size = 256;
    /* Data structure to hold the ZMQ_STREAM received data */
    uint8_t raw [256];
    size_t raw_size = 256;
    for(int i=0; i != n; ++i)
    {
        /*  Get HTTP request; ID frame and then request */
        id_size = zmq_recv (socket, id, 256, 0);
        assert (id_size > 0);
        std::cout << id_size << std::endl;
        raw_size = zmq_recv (socket, raw, 256, 0);

        /* Closes the connection by sending the ID frame followed by a zero response */
        zmq_send (socket, id, id_size, ZMQ_SNDMORE);
        zmq_send (socket, 0, 0, 0);
        /* NOTE: If we don't use ZMQ_SNDMORE, then we won't be able to send more */
        /* message to any client */
    }
    std::cout << "Done" << std::endl;
    int i;
    std::cin >> i;
    zmq_close (socket); zmq_ctx_destroy (ctx);
    return 0;
}

Cheers,
  Jens

--
Jens Auer | CGI | Software-Engineer
CGI (Germany) GmbH & Co. KG
Rheinstraße 95 | 64295 Darmstadt | Germany
T: +49 6151 36860 154
jens.auer at cgi.com<mailto:jens.auer at cgi.com>
Unsere Pflichtangaben gemäß § 35a GmbHG / §§ 161, 125a HGB finden Sie unter de.cgi.com/pflichtangaben<http://de.cgi.com/pflichtangaben>.

CONFIDENTIALITY NOTICE: Proprietary/Confidential information belonging to CGI Group Inc. and its affiliates may be contained in this message. If you are not a recipient indicated or intended in this message (or responsible for delivery of this message to such person), or you think for any reason that this message may have been addressed to you in error, you may not use or copy or deliver this message to anyone else. In such case, you should destroy this message and are asked to notify the sender by reply e-mail.
________________________________
Von: zeromq-dev-bounces at lists.zeromq.org [zeromq-dev-bounces at lists.zeromq.org]" im Auftrag von "KIU Shueng Chuan [nixchuan at gmail.com]
Gesendet: Montag, 21. März 2016 15:38
An: ZeroMQ development list
Betreff: Re: [zeromq-dev] Empty message does not close ZMQ_STREAM socket?

Hi Jens,

I tried out the pair of programs in your original post. Indeed, I got the behavior that you described using ZeroMQ 4.1.2.

Putting the server code into a while loop did the trick.
```c++
server.bind(address);
while (1)
{
   // recv connection
   // send disconnection
}
int i;
std::cin >> i;

```

I think in my own code, I have only ever used it in this forever loop fashion. Hmm...


On Mon, Mar 21, 2016 at 9:11 PM, Auer, Jens <jens.auer at cgi.com<mailto:jens.auer at cgi.com>> wrote:
Hi,

Thanks for the suggestion. I have modified my example to copy the id into a new message, but it did not change anything. I have also tried a second version of the server side which is basically the example provided at the bottom of the manual page:
int main2(int argc, char* argv[]) {
        int n = std::atoi(argv[1]);
        void *ctx = zmq_ctx_new ();
        /* Create ZMQ_STREAM socket */
        void *socket = zmq_socket (ctx, ZMQ_STREAM);

        int rc = zmq_bind (socket, "tcp://127.0.0.1:5000<http://127.0.0.1:5000>");
        /* Data structure to hold the ZMQ_STREAM ID */
        uint8_t id [256];
        size_t id_size = 256;
        /* Data structure to hold the ZMQ_STREAM received data */
        uint8_t raw [256];
        size_t raw_size = 256;
        for(int i=0; i != n; ++i)
        {
                /*  Get HTTP request; ID frame and then request */
                id_size = zmq_recv (socket, id, 256, 0);
                assert (id_size > 0);
                std::cout << id_size << std::endl;
                raw_size = zmq_recv (socket, raw, 256, 0);

                /* Closes the connection by sending the ID frame followed by a zero response */
                zmq_send (socket, id, id_size, ZMQ_SNDMORE);
                zmq_send (socket, 0, 0, ZMQ_SNDMORE);
                /* NOTE: If we don't use ZMQ_SNDMORE, then we won't be able to send more */
                /* message to any client */
        }
        std::cout << "Done" << std::endl;
        int i;
        std::cin >> i;
        zmq_close (socket); zmq_ctx_destroy (ctx);
        return 0;
}

This has the same problem as described before that the socket is not closed and I even receive an empty message at the client’s side.

Cheers,
  Jens

--
Dr. Jens Auer | CGI | Software Engineer
CGI Deutschland Ltd. & Co. KG
Rheinstraße 95 | 64295 Darmstadt | Germany
T: +49 6151 36860 154
jens.auer at cgi.com<mailto:jens.auer at cgi.com>
Unsere Pflichtangaben gemäß § 35a GmbHG / §§ 161, 125a HGB finden Sie unter de.cgi.com/pflichtangaben<http://de.cgi.com/pflichtangaben>.

CONFIDENTIALITY NOTICE: Proprietary/Confidential information belonging to CGI Group Inc. and its affiliates may be contained in this message. If you are not a recipient indicated or intended in this message (or responsible for delivery of this message to such person), or you think for any reason that this message may have been addressed to you in error, you may not use or copy or deliver this message to anyone else. In such case, you should destroy this message and are asked to notify the sender by reply e-mail.

From: zeromq-dev-bounces at lists.zeromq.org<mailto:zeromq-dev-bounces at lists.zeromq.org> [mailto:zeromq-dev-bounces at lists.zeromq.org<mailto:zeromq-dev-bounces at lists.zeromq.org>] On Behalf Of KIU Shueng Chuan
Sent: 21 March 2016 11:43
To: ZeroMQ development list
Subject: Re: [zeromq-dev] Empty message does not close ZMQ_STREAM socket?


There's something in the manpage that your code doesn't do.

> To open a connection to a server, use the zmq_connect call, and then fetch the socket identity using the ZMQ_IDENTITY zmq_getsockopt call.

I don't recall if this was strictly necessary but I see in my code that I did fetch the identity but immediately discarded it.

I have some python scripts here where the server code disconnects the client.
https://github.com/pijyoi/test_zmqstream
See zmqstream_publisher.py and zmqstream_subscriber.py
On 21 Mar 2016 5:07 pm, "Auer, Jens" <jens.auer at cgi.com<mailto:jens.auer at cgi.com>> wrote:
Hi,

I am trying to close a TCP socket over a ZMQ_STREAM by sending an identity frame followed by an empty message, as described in the manual ("To close a specific connection, send the identity frame followed by a zero-length message"). I have a simple client/server example:
#include <zmq.hpp>
#include <iostream>
#include <cstdlib>

int main2() {
    std::string address = "tcp://127.0.0.1:5000<http://127.0.0.1:5000>";

    zmq::context_t zmq;
    zmq::socket_t server(zmq, ZMQ_STREAM);

    server.bind(address);

    zmq::message_t id;
    zmq::message_t m;
    server.recv(&id);
    server.recv(&m);
    std::cout << "Connection received: " << id.size() << std::endl;

    zmq::message_t empty{};

    server.send(id, ZMQ_SNDMORE);
    server.send(empty, ZMQ_SNDMORE );

    int i;
    std::cin >> i;

    return 0;
}

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

int main() {
    std::string address = "tcp://127.0.0.1:5000<http://127.0.0.1:5000>";

    zmq::context_t zmq;
    zmq::socket_t client(zmq, ZMQ_STREAM);

    client.connect(address);

    zmq::message_t m3;
    zmq::message_t m4;
    client.recv(&m3);
    client.recv(&m4);

    std::cout << "Connection established" << std::endl;

    {
        zmq::message_t m5;
        zmq::message_t m6;
        client.recv(&m5);
        client.recv(&m6);
    }

    std::cout << "Connection closed" << std::endl;
    int i;
    std::cin >> i;

    return 0;
}

When I start the server and then the client, the server will receive the connection message, but the empty message does not close the socket:
./stream_s 2
Connection received: 5
/tmp/stream_c
Connection established

tcp        0      0 127.0.0.1:5000<http://127.0.0.1:5000>          0.0.0.0:*               LISTEN      32615/./stream_s
tcp        0      0 127.0.0.1:5000<http://127.0.0.1:5000>          127.0.0.1:34270<http://127.0.0.1:34270>         ESTABLISHED 32615/./stream_s
tcp        0      0 127.0.0.1:34270<http://127.0.0.1:34270>         127.0.0.1:5000<http://127.0.0.1:5000>          ESTABLISHED 32618/stream_c

I have also created a second example where the server sends the close message twice. Here, the client actually receives the close message as an empty message. Why is this even possible over a ZMQ_STREAM socket?

I am using ZeroMQ 4.1.4, so the notification messages should be enabled by default without setting ZMQ_STREAM_NOTIFY, and I have also tested 4.1.2 to check for a regression.

Best wishes,
  Jens

_______________________________________________
zeromq-dev mailing list
zeromq-dev at lists.zeromq.org<mailto:zeromq-dev at lists.zeromq.org>
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

_______________________________________________
zeromq-dev mailing list
zeromq-dev at lists.zeromq.org<mailto:zeromq-dev at lists.zeromq.org>
http://lists.zeromq.org/mailman/listinfo/zeromq-dev


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20160321/44b351b8/attachment.htm>


More information about the zeromq-dev mailing list