1. 程式人生 > >ZeroC Ice介紹與簡單demo構建

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)客戶端收到服務端的返回值,列印該返回值。