libzmq icon indicating copy to clipboard operation
libzmq copied to clipboard

Behaviour of binding a second (UDP)socket on the same endpoint

Open sphaero opened this issue 3 years ago • 2 comments

Issue description

What should happen if I bind a second (udp) socket to the same endpoint?

Environment

Currently testing Linux and OSX. I'm using an external process to send some udp data:

oscsend localhost 1234 /sample/address iTfs 1 3.14 hello
  • libzmq version : a01d259db372bff5e049aa966da4efce7259af67
  • OS: Linux Debian testing and OSX 10.15

Minimal test code / Steps to reproduce the issue

#include "zmq.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

int main (void)
{
  void *context = zmq_ctx_new ();
  void *data_socket = zmq_socket (context, ZMQ_DGRAM);

  int rc = zmq_bind(data_socket, "udp://*:1234");
  if (rc == -1) {

      printf ("E: bind failed: %s\n", strerror (errno));
      return 1;
  }
  assert (rc == 0);

  // proof we are receiving data
  int count = 0;
  printf("starting recv\n");
  while (count < 10) {
    char buffer [100];
    rc = zmq_recv (data_socket, buffer, 100, 0);
    assert(rc > 0);
    printf ("Received Hello %.*s\n", 100, buffer);
    count++;
  }

  // bind another socket on the same port
  void *data_socket2 = zmq_socket (context, ZMQ_DGRAM);
  rc = zmq_bind(data_socket2, "udp://*:1234");
  if (rc == -1) {

      printf ("E: bind failed: %s\n", strerror (errno));
      return 1;
  }
  assert (rc == 0);

  count = 0;
  printf("starting recv\n");
  void *poller = zmq_poller_new ();
  zmq_poller_add (poller, data_socket, NULL, ZMQ_POLLIN);
  zmq_poller_add (poller, data_socket2, NULL, ZMQ_POLLIN);
  zmq_poller_event_t events [2];
  while (count<10)
  {
    int rc = zmq_poller_wait_all (poller, events, 2, -1);
    assert (rc >= 0);
    for (int i = 0; i < 2; ++i) {
      if (events[i].socket == data_socket && events[i].events & ZMQ_POLLIN) 
      {
        char buffer [100];
        rc = zmq_recv (events[i].socket, buffer, 100, 0);
        assert(rc > 0);
        printf ("Received data_socket %.*s\n", 100, buffer);
        count++;
      }
      else if (events[i].socket == data_socket2 && events[i].events & ZMQ_POLLIN) 
      {
        char buffer [100];
        rc = zmq_recv (events[i].socket, buffer, 100, 0);
        assert(rc > 0);
        printf ("Received data_socket2 %.*s\n", 100, buffer);
        count++;
      }
    }
  }
  return 0;
}

What's the actual result?

Linux

...
Received data_socket2 127.0.0.1:52448
Received data_socket2 /sample/address

On OSX no data is received after binding the second socket.

What's the expected result?

Not sure what the behaviour should be but I guess the linux behaviour is right or both sockets should receive the data.

sphaero avatar Feb 04 '22 14:02 sphaero


#include "zmq.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

int main (void)
{
  // Create a context for the first socket
  void *context = zmq_ctx_new ();
  void *data_socket = zmq_socket (context, ZMQ_DGRAM);

  int rc = zmq_bind(data_socket, "udp://*:1234");
  if (rc == -1) {
      printf ("E: bind failed: %s\n", strerror (errno));
      return 1;
  }
  assert (rc == 0);

  // Proof we are receiving data
  int count = 0;
  printf("Starting recv on data_socket\n");
  while (count < 10) {
    char buffer [100];
    rc = zmq_recv (data_socket, buffer, 100, 0);
    assert(rc > 0);
    printf ("Received data_socket: %.*s\n", 100, buffer);
    count++;
  }

  // Create a separate context for the second socket
  void *context2 = zmq_ctx_new ();
  void *data_socket2 = zmq_socket (context2, ZMQ_DGRAM);
  rc = zmq_bind(data_socket2, "udp://*:1234");
  if (rc == -1) {
      printf ("E: bind failed: %s\n", strerror (errno));
      return 1;
  }
  assert (rc == 0);

  count = 0;
  printf("Starting recv on data_socket2\n");
  void *poller = zmq_poller_new ();
  zmq_poller_add (poller, data_socket, NULL, ZMQ_POLLIN);
  zmq_poller_add (poller, data_socket2, NULL, ZMQ_POLLIN);
  zmq_poller_event_t events [2];
  while (count < 10)
  {
    int rc = zmq_poller_wait_all (poller, events, 2, -1);
    assert (rc >= 0);
    for (int i = 0; i < 2; ++i) {
      if (events[i].socket == data_socket && events[i].events & ZMQ_POLLIN) 
      {
        char buffer [100];
        rc = zmq_recv (events[i].socket, buffer, 100, 0);
        assert(rc > 0);
        printf ("Received data_socket: %.*s\n", 100, buffer);
        count++;
      }
      else if (events[i].socket == data_socket2 && events[i].events & ZMQ_POLLIN) 
      {
        char buffer [100];
        rc = zmq_recv (events[i].socket, buffer, 100, 0);
        assert(rc > 0);
        printf ("Received data_socket2: %.*s\n", 100, buffer);
        count++;
      }
    }
  }

  // Close the contexts and sockets
  zmq_close(data_socket);
  zmq_close(data_socket2);
  zmq_ctx_destroy(context);
  zmq_ctx_destroy(context2);

  return 0;
}


ljluestc avatar May 18 '24 19:05 ljluestc

Are you saying this does work?

sphaero avatar May 21 '24 11:05 sphaero