0

我正在使用这个程序来测试一个PULL带有ROUTER. 我创建/绑定 a 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();
}

结果

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

临时修复

如果我通过取消注释添加一点延迟Thread.currentThread().sleep(2000);,则消息已成功传递,但我鄙视使用睡眠和等待,它会创建混乱和脆弱的代码,但更重要的是,没有回答“为什么?”

问题

  • 为什么会这样?据我了解,“后期加入”仅适用于 PUB/SUB 套接字。
  • PULL 与 ROUTER 是无效的套接字组合吗?我将它用于聊天程序,除了这个问题,它工作得很好。
4

1 回答 1

0

为什么会这样?

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

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

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

于 2013-09-08T21:50:14.600 回答