ICE同步调用与异步调用(2)

7 篇文章 0 订阅

7回调函数

        回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础。

        回调接口的原理很简单,ICE客户和服务器都具有双重角色,即充当服务器也是客户客户。对一些简单的异步处理过程,我们可以通过回调机制来实现。

7.1 定义接口文件

#pragma once

 

module Demo

{

 

    interface CallbackReceiver

    {

        void callback();

    };

 

    interface CallbackSender

    {

        void initiateCallback(CallbackReceiver* proxy);

        void shutdown();

    };

 

};

 

7.2 服务端实现代码

#include <Ice/Ice.h>

#include <CallbackSenderI.h>

 

using namespace std;

using namespace Demo;

 

class CallbackServer : public Ice::Application

{

public:

 

    virtual int run(int, char*[]);

};

 

int

main(int argc, char* argv[])

{

    CallbackServer app;

    return app.main(argc, argv);

}

 

int

CallbackServer::run(int argc, char*[])

{

    if (argc > 1)

    {

        cerr << appName() << ": too many arguments" << endl;

        return EXIT_FAILURE;

    }

 

    Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Callback.Server");

    CallbackSenderPtr cbs = new CallbackSenderI;

    adapter->add(cbs, communicator()->stringToIdentity("callbackSender"));

    adapter->activate();

    communicator()->waitForShutdown();

    return EXIT_SUCCESS;

}

 

7.3 客户端实现代码

#include <Ice/Ice.h>

#include <callback.h>

 

using namespace std;

using namespace Demo;

 

class CallbackReceiverI : public CallbackReceiver

{

public:

 

     virtual void callback(const Ice::Current&)

     {

         cout << "received callback" << endl;

     }

};

 

class CallbackClient : public Ice::Application

{

public:

 

     CallbackClient();

 

     virtual int run(int, char*[]);

 

private:

 

     void menu();

};

 

int

main(int argc, char* argv[])

{

     CallbackClient app;

     return app.main(argc, argv);

}

 

//

// Since this is an interactive demo we don't want any signal

// handling.

//

CallbackClient::CallbackClient() :

    Ice::Application(Ice::NoSignalHandling)

{

}

 

int

CallbackClient::run(int argc, char*[])

{

     if (argc > 1)

     {

         cerr << appName() << ": too many arguments" << endl;

         return EXIT_FAILURE;

     }

     string strProxy = "callbackSender:default -h 192.168.11.100 -p 10000";

     Ice::CommunicatorPtr ic = communicator(); 

     Ice::ObjectPrx base = ic->stringToProxy(strProxy);

     CallbackSenderPrx sender =  CallbackSenderPrx::checkedCast(base);

 

     if (!sender)

     {

         cerr << appName() << ": invalid proxy" << endl;

         return EXIT_FAILURE;

     }

     string strEndpoints = "default -h 192.168.11.200 –p 10001";

     Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("Callback.Client", strEndpoints);

     CallbackReceiverPtr cr = new CallbackReceiverI;

 

     adapter->add(cr, ic->stringToIdentity("callbackReceiver"));

     adapter->activate();

     

     CallbackReceiverPrx receiver = CallbackReceiverPrx::uncheckedCast(

         adapter->createProxy(ic->stringToIdentity("callbackReceiver")));

 

     menu();

 

     char c;

     do

     {

         try

         {

              cout << "==> ";

              cin >> c;

              if (c == 't')

              {

                   sender->initiateCallback(receiver);

              }

              else if (c == 's')

              {

                   sender->shutdown();

              }

              else if (c == 'x')

              {

                   // Nothing to do

              }

              else if (c == '?')

              {

                   menu();

              }

              else

              {

                   cout << "unknown command `" << c << "'" << endl;

                   menu();

              }

         }

         catch (const Ice::Exception& ex)

         {

              cerr << ex << endl;

         }

     }

     while (cin.good() && c != 'x');

 

     return EXIT_SUCCESS;

}

 

void

CallbackClient::menu()

{

     cout <<

         "usage:\n"

         "t: send callback\n"

         "s: shutdown server\n"

         "x: exit\n"

         "?: help\n";

}

 

7.4 ACM(Active Connection Management)问题

       192.168.11.200:客户端IP地址,192.168.11.100:服务端IP地址。ICE内部有一个连接监视线程,查看当前端点的溢出时间控制。

      上面客户端控制台第一次发送“t”命令时,网络连接状态如下:

TCP    192.168.11.200:10001   192.168.11.100:2761    ESTABLISHED

TCP    192.168.11.200:17531   192.168.11.100:10000   ESTABLISHED

        默认60秒之后,连接即将断开:

TCP    192.168.11.200:10001   0.0.0.0:0              LISTENING

         ICE的ACM客户端连接服务器,Ice.ACM.Client=num表示客户端到服务器的连接空闲num秒后就会自动关闭,再次通讯时又会连接上。默认为60秒,一分钟。如果是0,表示客户端ACM不启用。服务端ACM Ice.ACM.Server = N,当客户端到服务端N秒没有数据发送时,服务端自动关闭连接。如果是0,表示服务端ACM不启用。

       因此,上述代码我们可以设置属性,定义连接时间:

    //Ice::CommunicatorPtr ic = communicator();

Ice::PropertiesPtr props = Ice::createProperties(argc, argv);

    props->setProperty("Ice.ACM.Server","0");  //客户端与服务端保持连接时间(0禁止)

    props->setProperty("Ice.ACM.Client","0");  //服务端与客户端保持连接时间(0禁止)

    Ice::InitializationData id;

    id.properties = props;

    Ice::CommunicatorPtr ic = Ice::initialize(id);

 

8双向连接(Bidirectional Connections)

        ICE的连接通常允许请求只在一个方向流动。如果一个应用程序的设计需要服务器会回调到客户端,服务器通常建立新的连接(如4章节的回调函数)。

图8.1 callback

        不幸的是当我们在网络限制条件下,服务器与客户端之间,往往只允许创建一个单独的连接。如图5.2所示,当客户端位于防火墙后面。

图8.2 与防火墙的回调函数。

        在两个双向连接流的方向上提供可能要求,以客户端用户现有的连接,使服务器发送到客户端回调请求。

          定义一个接口Callback.ice:

#pragma once

#include <Ice/Identity.ice>

module Demo

{

    interface CallbackReceiver

    {

        void callback(int num);

    };

    interface CallbackSender

    {

        void addClient(Ice::Identity ident);

    };

};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值