PULL插座没有足够快地连接到ROUTER

时间:2013-08-16 23:39:50

标签: java zeromq

我正在使用此程序使用PULL测试ROUTER套接字。我创建/绑定ROUTER,然后连接一个带有标识的PULL套接字; ROUTER然后使用其标识(基本的zeromq包络)发送专门为客户端发送的消息

测试计划

public static void main(String[] o){
    ZContext routerCtx = new ZContext();
    Socket rtr = routerCtx.createSocket( ZMQ.ROUTER);
    rtr.setRouterMandatory(true);
    rtr.bind("tcp://*:5500");

    ZContext clientCtx = new ZContext();
    Socket client1 = clientCtx.createSocket( ZMQ.PULL);
    client1.setIdentity("client1".getBytes());
    client1.connect("tcp://localhost:5500");

    try{
        //Thread.currentThread().sleep(2000);   
        rtr.sendMore("client1");
        rtr.sendMore("");
        rtr.send("Hello!");     

        System.out.println( client1.recvStr());
        System.out.println("Client Received: " + client1.recvStr());

    }catch(Exception e1){
        System.out.println( "Could not send to client1: " + e1.getMessage());
    }

    routerCtx.destroy();
    clientCtx.destroy();
}

结果

期望的结果是打印Client Received: Hello!",但是ROUTER会抛出与不可寻址消息一致的异常;我在这种情况下使用setRouterMandatory(true)抛出异常,但是,客户端显式设置了身份,服务器发送到该身份,所以我不明白为什么会引发异常。< / p>

临时修复

如果我通过取消注释Thread.currentThread().sleep(2000);来添加稍微的延迟,则消息传递成功,但我鄙视使用睡眠和等待,它会产生混乱和脆弱的代码,但更重要的是,没有回答& #34;为什么&#34;

问题

  • 为什么会这样?据我所知,"late joining"仅适用于PUB / SUB套接字。
  • 使用ROUTER拉出无效的套接字组合?我将它用于聊天程序,除了这个问题,它的效果很好。

1 个答案:

答案 0 :(得分:0)

  

为什么会这样?

你有竞争条件。 client1.connect调用会启动连接过程,但无法保证在您调用rtr.sendMore("client1");时建立实际连接。您的sleep()解决方法几乎证明了这一点。

PULL更改为DEALER是朝着正确方向迈出的一步,因为DEALER可以发送和接收。为了避免需要睡眠和等待,您必须更改协议。对上面的代码进行简单的更改就是让DEALER连接,然后立即向ROUTER发送“HELLO”消息(可能只是一个空消息)。必须重新设计路由器代码,使其在从DEALER收到HELLO消息之前不执行任何操作。收到HELLO消息后,您知道连接已成功建立,您可以安全地发送聊天消息。

此外,此协议不需要您的路由器提前知道客户端ID。相反,您可以从HELLO消息中提取它。从DEALER到ROUTER的消息保证是多部分消息,第一部分是客户端ID。