我正在尝试使用REQ / REP套接字同步我的PUB / SUB套接字。这在大多数时间都是有效的,但是有时在接收方法期间REP套接字被阻塞。我对PUB / REP和SUB / REQ使用相同的ZMQ上下文。因此,对于同步,我的订户正在向发布者发送请求。然后,发布者发回了答复。如果发布者收到了所有预期订阅者的请求,则同步完成。
发布者:
Publisher::Publisher(zmq::context_t & ctx) :
mZMQcontext(ctx), mZMQpublisher(mZMQcontext, ZMQ_PUB), mZMQSyncService(
mZMQcontext, ZMQ_REP)
{
mZMQpublisher.setsockopt(ZMQ_LINGER, 100);
}
void Publisher::bindSocket(std::string port)
{
mZMQpublisher.bind("tcp://*:" + port);
}
void Publisher::preparePubSynchronization(std::string port)
{
mZMQSyncService.bind("tcp://*:" + port);
}
void Publisher::synchronizePub(uint64_t expectedSubscribers)
{
// Synchronization with subscribers
uint64_t subscribers = 0;
while (subscribers < expectedSubscribers)
{
// >>>>> Is randomely blocked here <<<<<
std::string request = s_recv(mZMQSyncService);
s_send(mZMQSyncService, request);
subscribers++;
}
}
订户:
Subscriber::Subscriber(zmq::context_t & ctx) :
mZMQcontext(ctx), mZMQsubscriber(mZMQcontext, ZMQ_SUB)
{
mZMQsubscriber.setsockopt(ZMQ_LINGER, 100);
}
bool Subscriber::connectToPub(std::string ip, std::string port)
{
mZMQsubscriber.connect("tcp://" + ip + ":" + port);
}
bool Subscriber::prepareSubSynchronization(std::string ip, std::string port)
{
mSyncIP = ip;
mSyncPort = port;
}
// Helper function to get a new socket
zmq::socket_t* Subscriber::newSyncSocket()
{
zmq::socket_t* client = new zmq::socket_t(mZMQcontext, ZMQ_REQ);
client->connect("tcp://" + mSyncIP + ":" + mSyncPort);
client->setsockopt(ZMQ_LINGER, 0);
return client;
}
bool Subscriber::synchronizeSub()
{
zmq::socket_t* client = newSyncSocket();
int retries_left = 3;
std::string request = mOwner;
s_send(*client, request );
bool expect_reply = true;
while (expect_reply)
{
// Poll socket for a reply, with timeout
zmq::pollitem_t items[] = { { *client, 0, ZMQ_POLLIN, 0 } };
zmq::poll(&items[0], 1, REQUEST_TIMEOUT);
// If we got a reply, process it
if (items[0].revents & ZMQ_POLLIN)
{
// We got a reply from the publisher -> must match request
std::string reply = s_recv(*client);
if (reply == request)
{
// Valid reply
expect_reply = false;
}
} else if (--retries_left == 0)
{
// publisher seems to be offline, abandoning
delete client;
return false;
} else
{
// No response from publisher, retrying ...
// Old socket will be confused; close it and open a new one
delete client;
client = newSyncSocket();
// Send request again, on new socket
s_send(*client, request);
}
}
delete client;
return true;
}