You have chosen a great exercise, that's for sure!
Read them, they provide a basic request / response implementation using a custom proxy router-router with polling and should address your client-device problem.
The solution is synchronous, so any request sent from client blocks until it receives a response. Personally, I would like to use async for request and response for complete flexibility, but this solution is more complex. However, the book refers to Freelance and Dealer/Router examples illustrating an asynchronous request / response.
Here is an example of a many-to-many synchronous request / response. You MUST know how ZeroMq wrapping works in order to fully understand the mechanics of this approach; see example lbbroker1 .
Client
Set the client ID using setIdentity() ; important for routing the response.
The client sends requests for device1 , device2 , etc. In the loop; if the device exists, status messages returned from the specific device; otherwise, βno deviceβ is returned to the client.
Socket client = context.socket(ZMQ.REQ); client.setIdentity("client1".getBytes()); client.connect("tcp://localhost:5550"); for( int i = 0; i < 5; i++){ client.send("device" + i); String reply = client.recvStr(); log("Received message: " + reply); Thread.currentThread().sleep(1000); }
Device
The device sets the id in the same way as the client for unique routing.
The device sends device.send("DEVICEREADY") to the server to signal online availability.
The device executes recvStr() three times to read the full envelope from the server.
String deviceId = "device1" Socket device = context.socket(ZMQ.REQ); device.setIdentity(deviceId.getBytes()); device.connect( "tcp://localhost:5560"); device.send( "DEVICEREADY"); while (!Thread.currentThread().isInterrupted()) { String clientAddress = device.recvStr(); String empty = device.recvStr(); String clientRequest = device.recvStr();
Server (Router / Router)
User proxy using ROUTER sockets; clients connect to an external ROUTER connector, and devices connect to a server router. Polling servers on both message sockets.
Context context = ZMQ.context(1); Socket frontend = context.socket(ZMQ.ROUTER); Socket backend = context.socket(ZMQ.ROUTER); frontend.bind( "tcp://localhost:5550"); backend.bind( "tcp://localhost:5560"); Poller poller = new Poller(2); poller.register(frontend, Poller.POLLIN); poller.register(backend, Poller.POLLIN); while (!Thread.currentThread().isInterrupted()) { poller.poll(); //frontend poller if (poller.pollin(0)) { String clientId = frontend.recvStr(); String empty = frontend.recvStr(); //empty frame String deviceId = frontend.recvStr(); //if client is requesting to talk to nonexistent deviceId, //return message "no device", otherwise, create envelope and send //request on backend router to device. if( deviceMap.get( deviceId) == null ){ frontend.sendMore(clientId); frontend.sendMore(""); frontend.send("no deviceId: " + deviceId); } else { //request envelope addressed to specific device backend.sendMore(deviceId); backend.sendMore(""); backend.sendMore(clientId); backend.sendMore(""); backend.send("hello from " + clientId); } } //backend poller if(poller.pollin(1)){ String deviceId = backend.recvStr(); String empty = backend.recvStr(); String clientId = backend.recvStr(); //device signaling it ready //store deviceId in map, don't send a response if( clientId.equals("DEVICEREADY")) deviceMap.put(deviceId, deviceId); else { //the device is sending a response to a client //create envelope addressed to client, send on frontend socket empty = backend.recvStr(); String reply = backend.recvStr(); frontend.sendMore(clientId); frontend.sendMore(""); frontend.send(reply); } } }