• ICE 的回调


    使用分布式计算中间件ICE到现在已经有一年多了,在这一年里里面对ICE的理解、应用比较熟悉。

       使用ICE写分布式软件,确实是很方便:ICE比较稳定、可靠,调用返回速度低延迟,使用简单,学习曲线不是很陡。

        总之利用ICE开发分布式软件,是一个可行的选择。

        在实际的过程中,ICE客户端跟服务端的数据流动是单项的,也就是客户端获取服务端的一个代理,从而与服务端进行数据交互,如果服务端要主动给客户端数据的时候,则需要我们给服务端传去一个客户端的代理。这时客户端也是一个服务器。在ICE中客户端、服务端没有严格的限制。

        在ICE中有三种提供回调的方法,以下将具体介绍这三种方法:

        1:适合服务器、客户端在如下的环境。客户和服务器程序或者运行在同一个主机上,或者运行在没有网络限制的多个主机上。这样的环境下,提供回调是最简单的。

         以下是简单的例子,首先先写slice文件:

     // **********************************************************************
    //
    // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.
    //
    // This copy of Ice is licensed to you under the terms described in the
    // ICE_LICENSE file included in this distribution.
    //
    // **********************************************************************
    #ifndef CALLBACK_ICE
    #define CALLBACK_ICE
    module Demo
    {
    interface CallbackReceiver
    {
        void callback();
    };
    interface CallbackSender
    {
        void initiateCallback(CallbackReceiver* proxy);
        void shutdown();
    };
    };
    #endif

    这个例子直接从ICE提供的demo中获得的。

    然后利用ICE提供的slice2cpp程序,生成骨架代码,具体就不说了。

    接着客服端实现利用如下的方式,提供回调代理:

    CallbackSenderPrx senderPrx =

    CallbackSenderPrx::checkedCast( communicator()->propertyToProxy("Callback.CallbackServer"))

    "Callback.CallbackServer"是通过配置文件配置的,该代码是利用继承Ice::Application,重载它的main成员函数。communicator是ICE提供的通信器。

    以下,是客户端提供回调的形式化代码:

    Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Callback.Client");
    adapter->add(new CallbackReceiverI, communicator()->stringToIdentity("callbackReceiver"));
    adapter->activate();

    CallbackReceiverPrx twowayR = CallbackReceiverPrx::uncheckedCast(
     adapter->createProxy(communicator()->stringToIdentity("callbackReceiver")));

    然后调用:

    senderPrx ->initiateCallback(twowayR);

    这样就把客户端的一个回调代理传给服务端。

    不过这样的传回调在比较负责的网络环境下,回调是会失败的。在实际的开发过程中,我就遇到这样的问题。然后去文档中寻求,解决方法。

    我遇到的问题,在文档中Glacier有介绍,客户端和服务端的网络环境如图:


     

    在这样的情况下,ICE回调给客户端是失败的,原因是ICE通过那个回调对象,不能找到客户端的路由信息。

    因此有两种可选的方式,一种是利用Glacier,另外一种Bidirectional Connections(可能是要ICE3.2.0及其以后的版本才支持)。

      我在实际的过程中,是利用Bidirectional Connections解决了上面的那个问题,是通过了实际的测试。Glacier方法,我没实际测试过。

      因此,具体介绍Bidirectional Connections方法。在ICE文档3.2.1中提到,如何使用这个方法,大家有兴趣可以去看看。

      下面提供一些形式化的代码,并说明注意事项。

       还是先把slice文件(来自ICE DEMO)提供出来,以下是slice文件:

       // **********************************************************************
    //
    // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.
    //
    // This copy of Ice is licensed to you under the terms described in the
    // ICE_LICENSE file included in this distribution.
    //
    // **********************************************************************
    #ifndef CALLBACK_ICE
    #define CALLBACK_ICE
    #include <Ice/Identity.ice>
    module Demo
    {
    interface CallbackReceiver
    {
        void callback(int num);
    };
    interface CallbackSender
    {
        void addClient(Ice::Identity ident);
    };
    };
    #endif

    客户端的形式化代码:

       CallbackSenderPrx server = 
            CallbackSenderPrx::checkedCast(communicator()->propertyToProxy  

            ("Callback.Client.CallbackServer"));

        Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("");
        Ice::Identity ident;
        ident.name = IceUtil::generateUUID();
        ident.category = "";
        adapter->add(new CallbackReceiverI, ident);
        adapter->activate();
        server->ice_getConnection()->setAdapter(adapter);
        server->addClient(ident);

    服务端的形式化代码:

        CallbackReceiverPrx client = CallbackReceiverPrx::uncheckedCast(current.con->createProxy(ident));

         使用这个方式的一个注意事项:

    1:在配置文件

    #
    # ACM must be disabled for bidirectional connections
    #
    Ice.ACM.Client=0

    要将Ice.ACM.Client属性禁用掉。如果回调对象被关闭的话,只能重新

        if(server->ice_getConnection()->getAdapter() == NULL)

             server->ice_getConnection()->setAdapter(adapter);
        server->addClient(ident);

    因为ICE有一个机制如果在一定的时间内,没有发生数据交互,连接会被关闭

       其实也可以利用一个hook线程对回调代理进行ice_ping()。

    2:利用Bidirectional Connections,这样的代理是在原来的连接基础上建立起来的。因此不能修改回调代理的安全、超时等属性。

  • 相关阅读:
    让HTML5来为你定位(转)
    Web开发者应知的URL编码知识(转)
    Web开发:URL编码与解码(转)
    用virtualenv建立多个Python独立开发环境(转)
    使用Ajax方式POST JSON数据包(转)
    俞敏洪:我和马云就差了8个字...(转)
    HTTP返回码中301与302的区别(转)
    Postgresql 正则表达式(转)
    【双十一狂欢,一触即发!】安全圈的学习节|绝对省钱攻略
    安全运维中基线检查的自动化之ansible工具巧用
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9410073.html
Copyright © 2020-2023  润新知