ZeroC Ice介绍与简单demo构建

本文主要介绍ZeroC Ice的相关知识,以及如何构建一个Ice的demo程序。

1. ZeroC Ice介绍

Ice(Internet Communications Engine)是一个面向对象的RPC框架,它可以帮助你轻松地构建分布式应用。通过使用Ice,用户可以将更多的注意力放在自己应用程序的逻辑上,至于底层网络程序接口的交互则由Ice负责。通过使用Ice,用户不需要再为一些细节担忧,例如开放式网络连接、网路传输的序列化和反序列化,以及连接的失败重传问题。

ZeroC Ice的客户端和服务端的架构图如下:


2. demo构建

说明:本文介绍的demo程序是在Centos 7上、使用C++语言开发的,对应的Ice版本为3.6.4。

2.1 安装Ice

1. 添加Ice的yum仓库:

cd /etc/yum.repos.d
wget https://zeroc.com/download/Ice/3.6/el7/zeroc-ice3.6.repo

2. 安装Ice:

yum install ice-all-runtime ice-all-devel

2.2 编写Slice定义文件

开发Ice程序的第一步就是编写Slice定义文件,该文件包含了Ice应用程序需要用到的接口。

在本文中,我们编写名为Hello.ice的Slice定义文件,Hello.ice内容如下:

module Demo {
    interface Hello {
        string SayHello(string username);
    };
};

上面的Slice定义文件内,包括了Demo模块,Demo模块中又包含了Hello接口。当前,Hello接口仅提供了一个操作:SayHello。SayHello操作的具体功能需要我们后续去实现。

2.3 编译Slice定义文件

编译前面编写的Slice定义文件,生成编译C++所需要的文件,命令如下:

slice2cpp Hello.ice

根据Hello.ice,上面的命令会生成两个文件:Hello.h和Hello.cpp。其中:
Hello.h:Hello.h头文件包含了Slice定义文件中定义的Hello接口(当前,现在这个接口是以C++类型定义的),在客户端与服务端的源码中都要包含Hello.h。
Hello.cpp:Hello.cpp包含了Hello接口的实现源码。这些源码包括了针对客户端和服务端的(参数/返回值)类型指定及运行支持。例如,它包含了客户端的参数数据序列化,以及服务端数据反序列化。在客户端和服务端进行代码编译和连接的过程中,都需要包含Hello.cpp。

说明:从架构角度看,由Hello.ice生成的Hello.h和Hello.cpp,相当于C++的 proxies 和 skeletons。

2.4 编写接口处理类声明及实现代码

创建接口处理类HelloI,HelloI继承了生成类Hello(由*.ice文件生成)。在HelloI中定义了(*.ice文件中)SayHello操作的具体实现。

类HelloI声明代码(HelloI.h)如下:

#ifndef __HELLOI_H__
#define __HELLOI_H__

#include <Hello.h>

using namespace std;

class HelloI : public Demo::Hello
{
public:
    virtual string SayHello(const string&, const Ice::Current&);
};

#endif

类HelloI的实现代码(HelloI.cpp)如下:

#include <Ice/Ice.h>
#include <HelloI.h>

using namespace std;

string HelloI::SayHello(const string& s, const Ice::Current&)
{
    string wholestr;
    cout << "server receive msg: " << s << endl;
    wholestr = "hello " + s;
    cout << "server return msg: " << wholestr << endl;
    return wholestr;
}

注意:本文到现在为止,介绍的几个文件(Hello.ice、Hello.h、Hello.cpp、HelloI.h、HelloI.cpp)为本ZeroC Ice系列博客的demo搭建时使用的基础框架文件,后面对于ZeroC各个应用模式的demo搭建,如无特殊说明,均沿用了这五个基础文件。现给出ZeroC各应用模式的demo链接如下:

  • 最简单的Ice框架搭建,请参考本文后续部分。
  • 使用IceBox封装接口处理类HelloI实例的相关文章,请点击此处
  • 继承Ice::Application类,搭建Ice demo框架,请点击此处

2.5 编写服务端代码

服务端代码创建接口处理类HelloI的实例,并将该实例关联到指定的Ice对象ID(本例中Ice对象ID为“hello”),客户端通过这个Ice对象ID调用服务端(接口处理类中定义的)方法。

服务端代码(server.cpp)如下:

#include <Ice/Ice.h>
#include <HelloI.h>

using namespace std;

int main(int argc, char* argv[])
{
    int status = 0;
    Ice::CommunicatorPtr ic;
    try
    {
        ic = Ice::initialize(argc, argv);
        Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("HelloAdapter", "default -p 10000");
        Ice::ObjectPtr object = new HelloI;
        adapter->add(object, ic->stringToIdentity("hello"));
        adapter->activate();
        cout << "server started, waiting for client connect..." << endl;
        ic->waitForShutdown();
    }
    catch (const Ice::Exception& e)
    {
        cerr << e << endl;
        status = 1;
    }
    catch (const char* msg)
    {
        cerr << msg << endl;
        status = 1;
    }

    if (ic)
    {
        try
        {
            ic->destroy();
        }
        catch (const Ice::Exception& e)
        {
            cerr << e << endl;
            status = 1;
        }
    }

    return status;
}

2.6 编写客户端代码

客户端代码通过服务端提供的Ice对象ID连接服务端,并调用(与该Ice对象ID)相关的方法。

客户端代码(client.cpp)如下:

#include <Ice/Ice.h>
#include <Hello.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);
        Ice::ObjectPrx base = ic->stringToProxy("hello:default -p 10000");
        HelloPrx hello = HelloPrx::checkedCast(base);
        if (!hello)
        {
            throw "Invalid proxy";
        }
        string result = "";
        result = hello->SayHello("liitdar");
        cout << "client's result: " << result << endl;
    }
    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;
}

2.7 编译生成客户端和服务端的应用程序

编译生成服务端应用程序(server),命令如下:

g++ -o server -I. server.cpp Hello.cpp HelloI.cpp -lIce -lIceUtil -lpthread

编译生成客户端应用程序(client),命令如下:

g++ -o client -I. client.cpp Hello.cpp -lIce -lIceUtil -lpthread

2.8 运行服务端与客户端程序

在一个终端运行服务端程序,如下:

./server

新打开一个终端,运行客户端程序,如下:

./client

正常情况下,我们能够在上面的两个终端中看到服务端与客户端的信息交互情况,如下:

【服务端】:

【客户端】:

如果两个终端中出现了上述信息,说明demo程序部署成功了。

上述信息交互过程为:

a)服务端启动,等待客户端连接;
b)客户端连接服务端,发送“liitdar”到服务端,调用服务端的SayHello方法(“liitdar”作为SayHello方法的参数);
c)服务端执行SayHello方法,并在终端上打印相关信息;
d)服务端将SayHello方法的返回值返回给客户端;
e)客户端收到服务端的返回值,打印该返回值。


猜你喜欢

转载自blog.csdn.net/liitdar/article/details/80061658