I have a current implementation of ZMQ in my program that works great. I am initializing my monitor with ZMQ_EVENT_CONNECTED
then checking for the event with the ZMQ provided bool check_event(10)
- 10 is the timeout length.
I want to change my monitor initialization to ZMQ_EVENT_ALL
and handle each event differently. Say my socket randomly disconnects, I want to listen for that specific event and display an error to my user. I don't want the user to still attempt sending a message and be caught in limbo - which is the case now because I am only listening for the CONNECTED event and not looking for or handling other events.
How can I handle each specific event differently if check_event()
is only a bool? Is there something other than check_event()
that looks for an event? Maybe one that will return the events value for me to check against ? I am open to suggestions
My connect function is here.
void control::connect(std::string ipAddr) {
zmq::context_t context (1); // Creating context for connection.
zmq::socket_t socket(context, zmq::socket_type::req); // Setting socket with REQUEST type. Table is a REPLY type.
socket.set(zmq::sockopt::routing_id, "rtc"); // Setting the routing ID for the socket
// Monitor to check for socket being connected to table.
monitor.init(socket, "inproc://monitor", ZMQ_EVENT_CONNECTED); // Initialize the connection monitor.
int connectionAttempt = 0; // Holds number of connection attempts
// While the program is not connected to the rate table, attempt connection.
while(!isConnected){
try{
cout << "connecting...\n"; // Notify user of attempt to connect
connectionAttempt++; // increment attempt count
socket.connect(ipAddr); // Connect to the ip address
if(monitor.check_event(10)){ // Wait 10ms - *IF* the CONNECT event kicks
isConnected = true; // Set the connection bool
continue; // continue past the while loop
}
}
catch(zmq::error_t err){ // Catch any error
cout << "ERROR: " << err.what() << endl; // Output error
}
sleep(2); // Sleep for 2s if not connected - then re-try
// 2s * 15 iterations - If not connected within 30 seconds. Throw error, exit.
if(connectionAttempt == 15){
// TODO - turn this into an actual error.
cout << "\n\nERROR: Max Connection Attempts Exceded.\nPlease check cables and verify rate table is turned on.\nThen restart application.\n";
exit(3);
}
}
// NOTIFY OF APP COMMANDS
printf(" TYPE: 'HELP' for a list of available commands.\n");
printf(" TYPE: 'QUIT' to close the program.\n\n");
// DO-While loop to allow user to send commands.
do{
// Once we are connected, we want to listen for a disconenct event.
if(***CHECK FOR DISCONNECT HERE***){ isConnected = false; continue;}
sendCommand(socket, context);
}while(isConnected == true);
// Perform closing procedure if we get to this point.
closeConnection(ipAddr, socket, context);
}
SOLUTION:
This is the solution I came up with, I set an eventID variable with the events in from ZMQ. Then in my code I check the set eventID value.
class socketMonitor : public zmq::monitor_t {
public:
// listening for the on_event_connected event, notify user if successful.
void on_event_connected(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_CONNECTED;
eventName = "Connected";
}
void on_event_disconnected(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_DISCONNECTED;
eventName = "Disconnected";
}
void on_event_connect_retried(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_CONNECT_RETRIED;
eventName = "Connection Retired";
}
void on_event_listening(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_LISTENING;
eventName = "Listening";
}
void on_event_connect_delayed(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_CONNECT_DELAYED;
eventName = "Connect Delayed";
}
void on_event_accept_failed(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_ACCEPT_FAILED;
eventName = "Accept Failed";
}
void on_event_closed(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_CLOSED;
eventName = "Closed";
}
void on_event_bind_failed(const zmq_event_t& event, const char* addr) override {
eventID = ZMQ_EVENT_BIND_FAILED;
eventName = "Bind Failed";
}
int eventID;
std::string eventName;
};
and I then check it like this in my code...
socketMonitor monitor;
monitor.check_event(1);
if(monitor.eventID == ZMQ_EVENT_DISCONNECTED){
isConnected == false; // Set bool to false
monitor.eventID = 0; // Reset ID
}
So far this seems to be doing what I need it to do.