package cz.cuni.mff.d3s.been.mq; import org.jeromq.ZMQ; import org.jeromq.ZMQException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * Tcp-based message receiver. * * @author Martin Sixta */ public class TcpMessageReceiver implements IMessageReceiver<String> { /** Logging */ private static Logger log = LoggerFactory.getLogger(TcpMessageReceiver.class); /** * ZMQ.Context to use for the connection. */ private final ZMQContext context; /** * ZMQ.Socket to communicate with. */ private ZMQ.Socket socket; /** * Connection string. */ private final String connection; /** * Port the receiver is bind to. */ private int port; TcpMessageReceiver(final ZMQContext context, String host) { this.context = context; this.connection = Messaging.createTcpConnection(host); } @Override public boolean isConnected() { return socket != null; } @Override public int getPort() { return port; } @Override public synchronized void close() { if (isConnected()) { socket.close(); socket = null; } } /** * Bind this receiver for listening * * @throws MessagingException If the receiver cannot be bound */ public void bind() throws MessagingException { if (isConnected()) { return; // already connected } socket = context.socket(ZMQ.PULL); final PortRange range = RandomPortRangePicker.getRange(); port = socket.bindToRandomPort(connection, range.getFrom(), range.getTo()); if (port <= 0) { socket = null; throw new MessagingException("Cannot bind socket."); } log.debug("TcpMessageReceiver is bound to address {}:{} ", connection, port); } @Override public String receive() throws MessagingException { if (!isConnected()) { throw new MessagingException("Receive on unbound socket."); } try { byte[] bytes = socket.recv(); return new String(bytes); } catch (ZMQException e) { throw new MessagingException("Receive failed", e); } } /** * Create a {@link TcpMessageSender} for this receiver * * @return The sender */ public TcpMessageSender createSender() { return new TcpMessageSender(context, String.format("%s:%d", connection, port)); } }