Можно ли использовать zmq::poll() для архетипа сокета ZMQ_PAIR?
Можно ли использовать zmq::poll
с разъемом типа ZMQ_PAIR
? У меня есть следующий код:
zmq::context_t ctx;
// create an in-process publisher for testing purposes
zmq::socket_t pub( ctx, ZMQ_PAIR );
pub.connect( "inproc://SelectTest_oneMessage" );
SendString( pub, "test-message" );
// create an in-process subscriber for testing purposes
zmq::socket_t sub( ctx, ZMQ_PAIR );
sub.bind( "inproc://SelectTest_oneMessage" );
zmq::pollitem_t sel[1];
sel[0].socket = ⊂
sel[0].events = ZMQ_POLLIN;
int rc = zmq::poll( sel, 1, -1 );
ASSERT_TRUE( sel[0].revents & ZMQ_POLLIN );
zmq::message_t msg;
ASSERT_NE( sub.recv( &msg ), 0 );
ASSERT_NE( sub.recv( &msg ), 0 );
Но призыв к zmq::poll
терпит неудачу с исключением:
Socket operation on non-socket
Что я здесь не так делаю? Или это ожидаемое поведение для ZMQ_PAIR
Розетки?
2 ответа
Проблема была в этой строке:
sel[0].socket = ⊂
&
не должен был быть там. Код работает после изменения этого на:
sel[0].socket = sub;
Было трудно уловить эту проблему, потому что socket
поле этой структуры является void *
, что означает, что проверка типов не жалуется в любом случае.
Нет, это не запрещено .poll()
на ZMQ_PAIR
конечная точка (sub
)
Беда кажется с .connect()
до .bind()
API говорит это (выделение добавлено):
При подключении сокета к одноранговому адресу с помощью
zmq_connect()
сinproc
транспорта, конечная точка должна интерпретироваться как произвольная строка, идентифицирующая имя для подключения. До версии 4.0 его имя должно было быть предварительно создано путем назначения его как минимум одному сокету в том же контексте ØMQ, что и подключаемый сокет. Начиная с версии 4.0, порядокzmq_bind()
а такжеzmq_connect()
не имеет значения, как для типа транспорта TCP.
Поймайте точную точку, где собака похоронена:
// >>> https://stackru.com/a/44510552
// Report 0MQ version
//
/* ----------------------------------------------------------------- */
int major, minor, patch;
zmq_version ( &major, &minor, &patch ); std::cout << "[INF] ZeroMQ USES 0MQ-API version" << major << "." << minor << "." << patch << std::endl;
/* ----------------------------------------------------------------- */
zmq::context_t pure_inproc_ctx( 0 ); std::cout << "[INF] ZeroMQ CREATED a Zero-IOthreads .Context()-instance for pure-inproc:// transport-classes operations" << std::endl;
zmq::socket_t pub( pure_inproc_ctx, ZMQ_PAIR ); std::cout << "[INF] ZeroMQ DONE [pub] socket instantiation" << std::endl;
zmq::socket_t sub( pure_inproc_ctx, ZMQ_PAIR ); std::cout << "[INF] ZeroMQ DONE [sub] socket instantiation" << std::endl;
sub.setsockopt( ZMQ_LINGER, 0, 1 ); /* .setsockopt() */ std::cout << "[INF] ZeroMQ DONE [sub].setsockopt()" << std::endl;
sub.bind( "inproc://SelectTest_oneMessage" ); /* .bind() */ std::cout << "[INF] ZeroMQ DONE [sub].bind()" << std::endl;
pub.setsockopt( ZMQ_LINGER, 0, 1 ); /* .setsockopt() */ std::cout << "[INF] ZeroMQ DONE [pub].setsockopt()" << std::endl;
pub.connect( "inproc://SelectTest_oneMessage" ); /* .connect() */ std::cout << "[INF] ZeroMQ DONE [pub].connect()" << std::endl;
zmq::message_t aMessageToSEND ( 5 );
memcpy ( aMessageToSEND.data (), "Hello", 5 ); std::cout << "[INF] ZeroMQ CREATED a [Hello] Message" << std::endl;
pub.send ( aMessageToSEND ); std::cout << "[INF] ZeroMQ SENT a Message via [pub].send()" << std::endl;
zmq::pollitem_t sel[1];
sel[0].socket = sub;
sel[0].events = ZMQ_POLLIN; std::cout << "[INF] ZeroMQ DONE a .Poller() setup" << std::endl;
std::cout << "[INF] ZeroMQ WILL wait HERE infinitely for a first .Poller.poll() for a [sub].POLLIN Event" << std::endl;
int rc = zmq::poll( &sel [0], 1, -1 ); std::cout << "[INF] ZeroMQ EXIT from wait-state on a first .Poller.poll() [sub].POLLIN Event" << std::endl;
ASSERT_TRUE( sel[0].revents & ZMQ_POLLIN ); std::cout << "[INF] ZeroMQ DONE test on a first .Poller.poll() [sub].POLLIN Event" << std::endl;
zmq::message_t aMessageToRECV; std::cout << "[INF] ZeroMQ CREATED a aMessageToRECV Message-container instance" << std::endl;
ASSERT_NE( sub.recv( &aMessageToRECV ), 0 ); std::cout << "[INF] ZeroMQ DONE 1st test on [sub].recv() to immediately load aMessageToRECV-container" << std::endl;
ASSERT_NE( sub.recv( &aMessageToRECV ), 0 ); std::cout << "[INF] ZeroMQ DONE 2nd test on [sub].recv() to immediately load an already loaded container" << std::endl;