ICE C++ Hello World实例教程

1.  概述

本文演示了如何编写一个最简单的C++ICE(Internet Communications Engine)应用程序,包括必要环境的安装。该应用程序包含客户端和服务端两部分。当服务端正常运行时,运行客户端,将在服务端的标准输出上输出“Hello World”。

2.  安装Ubuntu

安装一份Ubuntu系统,可以是在物理机上安装,也可以在虚拟机上安装。本文中使用的Ubuntu版本为12.10

3. 安装ICE环境

进入Ubuntu桌面环境,按Ctrl + Alt + T打开终端界面,输入下面的命令

sudo apt-get install zeroc-ice34

此命令将会自动安装ICE环境。等待安装完成后,可以尝试运行slice2cpp命令,如果出现该命令的提示,则说明ICE环境已经成功安装。

ICE默认安装在/usr目录下,进入/usr目录,在include和lib目录中可以看到ICE相关的头文件目录以及动态链接库

4. 安装g++ 4.4

在编写C++ ICE程序时,需要使用g++进行编译。不过最新的g++版本太高,在编译时会有问题,ICE的官方文档中说明最高支持的g++版本为4.4,因此需要安装g++ 4.4版本。

sudo apt-get install g++-4.4

安装完成后,运行g++,显示找不到文件,这是由于系统中没有设置该命令指向的文件。使用以下命令建立命令和文件之间的关联。同时将c++命令也关联到该文件

sudo update-alternatives --install /usr/bin/g++ g++/usr/bin/g++-4.4 40

sudo update-alternatives --install /usr/bin/c++ c++/usr/bin/g++-4.4 40

(关于这条命令的详细信息,请参考 update-alternatives的相关说明)

运行完上面命令后,再次运行g++,则出现了g++的提示。查看一下g++的版本:

g++ -v或 c++ -v

可以发现,g++确实为4.4版本

5. 定义接口文件

编写ICE应用程序的第一步是定义slice文件。为了支持客户端和服务端使用不同的编程语言来实现,ICE定义了一种独立于各种开发语言,用来描述服务端提供的接口的语言,即slice。客户端根据slice文件可以知道服务端有哪些服务可以提供,并且知道应该以什么样的方式来使用服务端提供的服务。服务端则在slice文件定义的接口基础上去实现接口的功能。

新建一个目录,例如icehelloworld,将下面的内容保存为文件Printer.ice

module Demo {
interface Printer {
void printString(string s);
};
};

在这段文本中,定义了一个模块Demo。在此模块中有一个接口Printer。由于HelloWorld程序只需要服务端提供一个最简单的输出功能,因此这个接口目前也非常简单,只提供一个方法printString。该方法接收一个字符串类型的参数s。

6. 编写C++服务端

当使用具体的开发语言进行客户端或服务端的开发时,slice文件需要被转换为对应的开发语言能够使用的代码。ICE提供了这样的转换工具:

slice2cpp:  将slice文件转换为c++代码

运行以下命令,将slice文件转换为c++代码

slice2cpp Printer.ice

可以发现目录下多了两个文件:Printer.h和Printer.cpp。

slice转换为c++代码的过程是比较直观的。module将被转换为c++中的namespace,而interface将被转换为一个抽象类,interface中的方法也会被转换为该抽象类中的方法。服务端的代码从该抽象类派生一个具体类,并实现抽象类中的方法,这样就可以提供RPC接口的功能。远程过程调用

接下来就可以开始写服务端的代码了。新建文件,输入以下代码,保存为Server.cpp。这份服务代码看起来似乎比一个简单的HelloWorld程序要复杂很多,但是其中大部分代码都都是一些标准的初始化过程,真正与具体服务功能相关的代码只有几行而已。代码中的注释详细解释了代码的内容。

// 所有的ICE程序都需要包含ice.h, 这个文件包含了ICE的各种资源
#include <Ice/Ice.h> // 这个是前面的slice文件生成的c++头文件,包含了服务端提供的接口信息
#include <Printer.h>using namespace std;
using namespace Demo; // Printer.h 中生成的命名空间// 从Printer抽象类派生
class PrinterI : public Printer {
public:
//ICE接口方法中都会自动增加一个参数 Ice::Current,不过在这个HelloWorld程序中我们不需要用到
virtual void printString(const string& s, const Ice::Current&);
};// 这里就是RPC接口的实现代码
void PrinterI::printString(const string& s, const Ice::Current&)
{
// 这个接口实现的功能非常简单:在标准输出上打印接收到的字符串
cout << s << endl;
}// 服务端将从main函数开始运行
int main(int argc, char* argv[])
{
int status = 0;  //退出状态
//ic是一个指向ICE运行时资源的智能指针,通过ic可以获取运行时的各种资源。
Ice::CommunicatorPtr ic;
try {
//  Ice::initialize 初始化一个ICE运行时。传入 argc,argv是因为服务代码可能会处理命令行参数(本例中不需要)。
ic = Ice::initialize(argc, argv);
// 创建一个 ObjectAdapterPtr adapter,名字为 SimplePrinterAdapter。这个Adapter监听TCP/IP的10000端口
Ice::ObjectAdapterPtr adapter =
ic->createObjectAdapterWithEndpoints("SimplePrinterAdapter","tcp -p 10000");// 实例化一个PrinterI对象,该对象将为接口Printer提供服务
Ice::ObjectPtr object = new PrinterI;// 把PrinterI对象加入ObjectAdapter,标识名为SimplePrinter。当有客户端请求Printer的服务时,ObjectAdapter将会把请求转给PrinterI对象
adapter->add(object, ic->stringToIdentity("SimplePrinter"));// 启动ObjectAdapter, 此后ObjectAdapter开始处理实际的调用请求
adapter->activate();// 阻塞主线程,直到服务端的运行时被关闭
ic->waitForShutdown();} catch (const Ice::Exception& e) {
cerr << e << endl;
status = 1;
} catch (const char* msg) {
cerr << msg << endl;
status = 1;
}// 程序结束时,需要销毁ICE运行时资源。如果在程序退出时没有对ICE运行时进行销毁,可能引起未知错误
if (ic) {
try {
ic->destroy();
} catch (const Ice::Exception& e) {
cerr << e << endl;
status = 1;
}
}returnstatus;
}

编译服务端代码。在编译和连接时需要指定ICE头文件和动态链接库的位置

c++-I. -I/usr/include -c Printer.cpp Server.cpp

c++-o server Printer.o Server.o -L/usr/lib -lIce -lIceUtil

编译完成后,将在当前目录生成一个名为server的可执行文件

7. 编写C++客户端

新建一个文件,取名为Client.cpp,输入以下代码。

#include <Ice/Ice.h>
#include <Printer.h>using namespace std;
using namespace Demo;// 客户端只需要一个main函数,并且代码结构与服务端代码类似
int main(int argc, char* argv[])
{
int status = 0;
Ice::CommunicatorPtr ic;
try {
// 初始化ICE运行时
ic = Ice::initialize(argc, argv);// 使用字符串来生成一个对象代理
// 对象代理包含有服务端的服务对象的方法定义,并且负责和服务端的对象进行通信。因此客户端可以像使用本地对象一样使用服务端的对象
// 字符串中指定了对象代理对应的服务端的对象的名称,以及服务端对象监听的协议和端口。这些信息需要跟服务端中定义的信息一致
//ObjectPrx 在客户端代理服务器端
Ice::ObjectPrxbase = ic->stringToProxy("SimplePrinter:tcp -p 10000");
// 上面得到的是一个范型的对象代理,需要将它转换为Printer对象的代理,这样才能调用printString方法。
// checkedCast会与服务端进行通信,以判断该对象代理能否成功转换为Printer对象代理。如果转换失败,将返回空对象代理
PrinterPrx printer =PrinterPrx::checkedCast(base);
if (!printer)
throw "Invalid proxy";
// 调用Printer对象代理的printString方法。调用将会通过对象代理被发送到服务端
printer->printString("HelloWorld!");
} 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;
}

编译客户端代码,同样需要指定ICE头文件路径和动态链接库的位置

c++-I. -I/usr/include -c Printer.cpp Client.cpp

c++-o client Printer.o Client.o -L/usr/lib -lIce -lIceUtil

编译完成后,将在当前目录生成一个名为client的可执行文件

8. 测试

在当前目录运行 server

./server

成功运行后不会有任何输出

Crtl + Alt + T 新开一个终端,进入到之前的目录,运行client

./client

成功运行后同样不会有任何输出,并且程序会立即退出。

切换到运行server的终端,可以看到终端上输出了“Hello World”

9. 相关资源

ICE官方网站

http://www.zeroc.com

ICE源码下载

http://www.zeroc.com/download.html

文档中心(用户手册在线版)

http://doc.zeroc.com/display/Doc/Home

用户手册(PDF)

http://doc.zeroc.com/display/Ice/Ice+Manual

ICE C++ Hello World相关推荐

  1. ICE BOX 配置,使用----第一篇

    一 理论部分 (1) 为什么要使用icebox? icebox server代替了通常的server. icebox是为了方便集中管理多个ice服务而建立的. 它通过使用icebox服务器,把ice服 ...

  2. 英特尔第三代 Ice Lake 发布正面与 AMD EPYC PK,结果令人大跌眼镜!

    作者 | 夕颜 出品 | AI科技大本营(ID:rgznai100) 导读:传闻已久的第三代英特尔至强可扩展处理器,终于在北京风光最美的4月份发布了. 北京时间4月7日晚,在著名的网红打卡地,百年老首 ...

  3. ICE专题:ICE起步

    ICE初步 最早开始接触ICE是在2005,3月份,当时一个朋友向另一个正打算研究corba的朋友强烈的推荐了ICE. 参考:http://www.zeroc.com/ 1.什么是ICE? ICE(i ...

  4. 模型的可解释性:部分依赖图PDP和个体条件期望图ICE

    来源:Deephub Imba 本文约1800字,建议阅读5分钟 本文我们通过一个简单据集的回归示例了解了部分依赖图 (PDP) 和个体条件期望 (ICE) 图是什么,以及如何在 Python 中制作 ...

  5. 配置C++和C#开发ICE环境

    2019独角兽企业重金招聘Python工程师标准>>> C++配置环境 1.设置编译工具路径和配置编译命令: #编译命令,如果有多个文件就执行多次slice2cpp.exe命令 se ...

  6. Ice “Hello World”的实现

    2019独角兽企业重金招聘Python工程师标准>>> Ice简介: Ice (Internet Communications Engine),是一种面向对象的中间件平台,既然是平台 ...

  7. ZeroC ICE java异步实现方式(ami/amd)

    首先说说ami 和amd 的区别(以下为个人见解,仅供参考.如有疑问欢迎提出来) ami (异步方法调用): 仅仅基于ice 的同步方式扩展了异步的扩展方式,其他理念改动不大,使用起来好理解,但是服务 ...

  8. 谈谈自己对REST、SOA、SOAP、RPC、ICE、ESB、BPM知识汇总及理解

    2019独角兽企业重金招聘Python工程师标准>>> SOA: 维基百科解释:SOA:面向服务的软件架构(Service Oriented Architecture),是一种计算机 ...

  9. The Ice::Current Object

    The Ice::Current Object 服务器端Servant骨架方法(skeleton operation)都有一个Ice::Current类型的参数,这个对象定义如下: module Ic ...

  10. zeroc ice php,ZeroC ICE+PHP整合

    最近为了作分布式框架的技术选型,特意研究了多个分布式框架,恰好研究了Zeroc Ice 框架,特意记录以便后续查阅php 本文主要介绍win环境下PHP与ICE 环境的整合apache 首先咱们须要确 ...

最新文章

  1. 《基于压缩传感的匹配追踪重建算法研究》读书笔记
  2. 对于四叉树之(why?what?how)
  3. 几处早莺争暖树下一句是什么,几处早莺争暖树后一句
  4. ADO.NET之使用SqlConnection链接数据库
  5. golang变量定义细节及beego环境搭建细节记录
  6. 安装mysql8.0.11版本,并使用mybatis进行连接mysql遇到的问题
  7. C++以螺旋方式打印m * n矩阵的算法(附完整源码)
  8. 一款不错的网站压力测试工具webbench
  9. Android面试系列文章2018之内存管理之UI卡顿篇
  10. GoldenGate碎碎念
  11. Hive:动静态分区
  12. 线程同步---互斥锁和读写锁
  13. golang安装配置
  14. [NAS] Synology (群晖) DSM相关服务及套件安装
  15. 信息系统安全等级保护一些实施难点
  16. 前端工程师的三种级别,技术决定你能拿5K,还是15K,还是25K
  17. 金蝶软件工具集4.0
  18. Windows10下载安装openjdk11及配置环境变量
  19. ActiveX 部件不能创建对象解决思路
  20. 并查集详解(一个有爱的江湖故事)

热门文章

  1. MySQL 复制表结构、数据
  2. UE4搭建场景与特效文档—地形、水体、植被、雨雾效果
  3. Ubuntu18.04-ROS-Python-通过周立功Can发送16进制整数
  4. 了解KK音标以及相似音标如何学习记忆
  5. 互联网十大网络流行语
  6. ffmpeg 裁剪视频
  7. C++17之std::apply与std::make_from_tuple
  8. c语言如何添加程序图标,如何给C控制台程序添加图标
  9. 感恩有你 华为云学院伴你前行
  10. 小技巧|Cadence安装之后,原理图DSN文件的默认图标不对如何进行修改