zoukankan      html  css  js  c++  java
  • 第二章 学习ICE 3.0初读代码

    这一节大部分内容整理自ICE中文手册,在这里我特别感谢马维达同志的翻译给我们的学习带来了方便。

    读服务端代码

    文件server.cpp. 

    #include <Ice/Ice.h> 		
    #include "../print.h"
    using namespace std;
    using namespace Demo;

    //惯例,用后缀I 表示这个类实现一个接口
    class PrinterI : public Printer {
    public:
    virtual void printString(const string& s, const Ice::Current&);
    };
    /*
    打开print.h,看看PrinterI父类的定义

    namespace Demo {
    class Printer : virtual public Ice::Object {
    public:

    //纯虚函数,不能实例化
    virtual void printString(const std::string&,
    //第二个参数有缺省值,实现中可以不使用
    const Ice::Current&= Ice::Current()) = 0;
    };
    };
    */

    void PrinterI::printString(const string& s, const Ice::Current&)
    {
    cout << s << endl;
    }

    int main(int argc, char* argv[])
    {
    //程序的退出时的状态,就是否成功执行
    int status = 0;

    //来包含Ice run time 的主句柄 (main handle)
    Ice::CommunicatorPtr ic;

    try {
    //初始化Ice run time (argc和argv是run time命令参数;
    //就这个例子而言,服务器不需要任何命令行参数)。
    //initialize 返回一个指向Ice::Communicator对象的智能指针,
    //这个指针是Ice run time 的主句柄。
    ic = Ice::initialize(argc, argv);

    //调用Communicator 实例上的createObjectAdapterWithEndpoints,
    //创建一个对象适配器(比如:网卡就是一种适配器)。
    //参数是"SimplePrinterAdapter" (适配器的名字)
    //和"default -p 10000"(用缺省协议(TCP/IP),侦听端口10000 的请求。)
    //显然,在应用中硬编码对象标识和端口号,是一种糟糕的做法,
    //但它目前很有效;我们将在以后看到在架构上更加合理的做法。
    Ice::ObjectAdapterPtr adapter
    = ic->createObjectAdapterWithEndpoints(
    "SimplePrinterAdapter", "default -p 10000");

    //服务器端run time 已经初始化,实例化一个PrinterI 对象,
    //为我们的Printer 接口创建一个servant(serv 服务+-ant人,背一下单词)。
    Ice::ObjectPtr object = new PrinterI;

    //我们调用适配器的add,告诉它有了一个新的servant ;
    //传给add 的参数是刚才实例化的servant,再加上一个标识符。
    //在这里,"SimplePrinter" 串是servant 的名字
    //(如果我们有多个打印机,每个打印机都可以有不同的名字,
    //更正确的说法是,都有不同的对象标识)。
    adapter->add(object,
    Ice::stringToIdentity("SimplePrinter"));

    //调用适配器的activate 方法激活适配器
    //(适配器一开始是在暂停(holding)状态创建的;
    //这种做法在下面这样的情况下很有用:
    //我们有多个servant,它们共享同一个适配器,
    //而在所有servant实例化之前我们不想处理请求)。
    //一旦适配器被激活,服务器就会开始处理来自客户的请求。
    adapter->activate();

    //最后,我们调用waitForShutdown。
    //这个方法挂起发出调用的线程直到服务器实现终止
    //——或者是通过发出一个调用关闭run time,
    ic->waitForShutdown();
    }
    catch (const Ice::Exception& e) {
    cerr << e << endl;
    status = 1;
    } catch (const char* msg) {
    cerr << msg << endl;
    status = 1;
    }
    if (ic) {
    try {

    //必须调用Communicator::destroy结束Ice run time。
    //destroy 会等待任何还在运行的操作调用完成。
    //此外, destroy 还会确保任何还未完成的线程都得以汇合(joined),
    //并收回一些操作系统资源,比如文件描述符和内存。
    //决不要让你的main 函数不调用destroy 就终止,
    //否则,后果无法想象。
    ic->destroy();

    } catch (const Ice::Exception& e) {
    cerr << e << endl;
    status = 1;
    }
    }
    return status;
    }

    注意,尽管以上的代码不算少,但它们对所有的服务器都是一样的。你可以把这些代码放在一个辅助类里,然后就无需再为它费心了(Ice 提供了这样的辅助类,叫作Ice::Application,参见 10.3.1 节) 。就实际的应用代码而言,服务器只有几行代码:六行代码定义PrinterI 类,再加上三2 行代码实例化一个PrinterI 对象,并向对象适配器注册它。

    读客户端代码

    文件client.cpp. 

    #include <Ice/Ice.h>
    #include "..\print.h"
    using namespace std;
    using namespace Demo;
    int main(int argc, char* argv[])
    {
    int status = 0;
    Ice::CommunicatorPtr ic;
    try {
    ic = Ice::initialize(argc, argv);

    //stringToProxy 返回的代理(Proxy)类型是Ice::ObjectPrx,
    //这种类型位于接口和类的继承树的根部(接口的基类)。
    Ice::ObjectPrx base
    =ic->stringToProxy( "SimplePrinter:default -p 10000");

    //但要实际要与我们的打印机交谈,
    //我们需要的是Printer 接口、不是Object 接口的代理。
    //为此,需要调用PrinterPrx::checkedCast 进行向下转换(向下转型)。
    //这个方法会发送一条消息给服务器,
    //询问“这是Printer 接口的代理吗?”
    //如果回答“是”,就会返回Printer 的一个代理;
    //如果代理代表的是其他类型的接口,返回一个空代理
    PrinterPrx printer = PrinterPrx::checkedCast(base);

    //测试向下转型是否成功,若不成功,就抛出出错消息并终止客户。
    if (!printer) throw "Invalid proxy";

    //现在,我们在我们的地址空间里有了一个激活的代理,
    //可以调用printString 方法,
    //把享誉已久的 "Hello World!" 串传给它。
    //服务器会在它的终端上打印这个串。
    printer->printString("Hello World!");
    }
    catch (const Ice::Exception& ex) {
    cerr << ex << endl;
    status = 1;
    } catch (const char* msg) {
    cerr << msg << endl;
    status = 1;
    }
    if (ic)
    ic->destroy();
    return status;
    }

    如果出现任何错误,客户会打印一条出错消息。例如,如果我们没有先启动服务器就运行客户,我们会得到:

    Network.cpp:471: Ice::ConnectFailedException:
    connect failed: Connection refused

    (由于windows下的命令行窗口在出错后会一闪就消失,不过我们可以在client.cpp的main函数的return status;之前加上system("PAUSE");然后再在VS2003.net中把client设置为启动项目,重新编译,运行。OK,可以看到结果了。)

  • 相关阅读:
    高效App运营必须get的七个推送技巧
    如何预测您的用户即将流失?
    HMS Core赋能移动金融,为行业注入增长新动力
    做好自定义预测,探寻产品增长动能
    Unity平台 | 快速集成华为AGC云数据库服务
    HMS Core Insights第一期直播回顾 – 深入浅出,创新技术与开发者共同推进行业发展!
    多种细分方式浏览销售数据,IAP助您有效洞察市场收益效果
    Unity | 快速集成华为AGC云存储服务
    awk命令
    反转字符串
  • 原文地址:https://www.cnblogs.com/buffer/p/1597747.html
Copyright © 2011-2022 走看看