惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
有赞技术团队
有赞技术团队
J
Java Code Geeks
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
酷 壳 – CoolShell
酷 壳 – CoolShell
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
博客园 - 【当耐特】
The GitHub Blog
The GitHub Blog
Recent Announcements
Recent Announcements
The Cloudflare Blog
Microsoft Azure Blog
Microsoft Azure Blog
腾讯CDC
Vercel News
Vercel News
IT之家
IT之家
MyScale Blog
MyScale Blog
博客园_首页
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
罗磊的独立博客

博客园 - liuym

TB 编程整理 二 示例程序一 - liuym - 博客园 一 VC2008环境中ICE的配置 无法定位序数 3109 于LIBEAY32.dll - liuym 转:Virtual List的使用方法 转:VC++编程之CListCtrl控件的使用 2 转:VC++编程之CListCtrl控件的使用 好用 转:删除,修改注册表中需要设置权限的项 转:软件能够修复硬盘吗?―硬盘损坏全分析 转:CWnd 对象怎么和 HWND 窗口句柄相互转化 VC 多文档窗口 子窗口最大化时切换窗口 窗口没有最大化显示的问题 转:Windows VC6编译安装Boost库 转:送给那些一心想要传送文件的朋友(TCP协议).cpp-from CSDN 转:如何去了解、熟悉一个已经开发完的项目 进行维护、二次开发或者升级 递归创建文件夹 DLL中资源和主程序资源冲突 - liuym - 博客园 转:一种巧妙的删除程序自己的方法 转:双缓冲图形刷新技术 和 WGF双缓冲绘图框架 软件保护建议(转)
三 ICE开发初级研究
liuym · 2010-12-17 · via 博客园 - liuym

http://www.acejoy.com/bbs/viewthread.php?tid=2878&extra=page%3D1

ICE开发初级研究(一)

最近一段一直在忙于工作,事情比较多,除了偶尔在这里看看帖子,一直没有写什么东西。再加上忙于PurenessScopeSerever0.72版本的开发,争取0.72版再次给大家带来一些提升。其实想想,技术这种东西,并非一定要高深到谁也看不懂才叫牛。技术这样的东西,分享是很关键的。只有简单好用的技术,才会获得大规模的应用。

ICE这个东西,说实话以前我比较惧怕。到处看到的文章都是说,重量级的中间件,虽说是源于Corba,但是复杂度感觉不低于ACE。网上搜索ICE也都是比较基础的应用。最近工作用到了,想跟着工作的进度,陆续写一些ICE有关的实际应用。供大家参考和使用,抛砖引玉。这里特别感谢True的大力支持。现在看来,ICE还是不用惧怕的,ACE都能活下来,再看ICE实际变的简单了,呵呵。里面难免有些偏颇之处,请大家指正。

废话少说,要用ICE,需要先去官网下载一个ICE的开发库。

ICE的开发官网是http://www.zeroc.com,目前最新版本是3.4.1。

下载地址为:http://www.zeroc.com/download.html 这里我吃了一个亏(我在windows下使用,linux下倒是少了这些麻烦),因为没注意版本,我本人用的是VS2005,结果后来编码完后,运行竟然到处报错。后来才知道ICE的3.4.1只支持VS2008 SP1以后的开发环境(感觉怎么ICE的开发者就不能像ACE的开发者那样,支持多版本的编译器呢?),如果你是VS2005环境的话,建议下载3.3.1,如果是2008,建议下载3.4.0,如果是2008 SP1之后的版本,建议使用3.4.1。

如果是windows推荐下载msi版本,linux的话下载rpm,安装都比较省事,一路下一步就行了。

安装后打开环境变量,按照ACE的推荐那样设置一下你的ICE路径

然后打开你的VS2005,先建立一个服务器端(win32控制台程序)。(我的环境变量叫做ICE_ROOT)

然后在打开工程属性,里面添加C++附加路径($(ICE_ROOT\include))和你的lib附加路径($(ICE_ROOT)\lib),然后添加需要用到的iced.lib iceutild.lib

行了,这个工程就可以写ICE的程序了。

ICE使用前需要定义一个接口文件。一般是*.ice命名的(*是你起的名字,比如我的例子是TestICE.ice)

#ifndef _TESTICE_H

#define _TESTICE_H

module Test

{

        interface TestICE

        {

                int ping();

                int GetTime(out string strTime);

        };

};

#endif

这里是一个接口文件,我来给大家一行行解释。(其实大部分写法都是固定的)

首先,你必须定义你的接口的一个NameSpace的名字。

这里比如module Test

意思就是你声明了一个叫做Test的命名空间,这个是很重要的,因为未来在你的代码中,要写上using namespace Test。

下面是

interface TestICE 

这里是你声明的接口名称。这个就像把很多网线捆起来的束,在访问的时候,要先找到束,再找里面对应的接口。这样做,很方便管理你的接口,比如你可以定义一个DB接口集合,一个Logic接口集合。。。。层次感会跟清晰。

我在我的TestICE里面,定义了两个函数。

int ping();

int GetTime(out string strTime);

这里,我这两个函数都没有具体实现,呵呵,只是为了测试而已。

然后,这个文件写好了,进入你的ICE的安装路径,进入bin目录,然后cmd进入这个目录。在命令行敲入slice2cpp TestICE.ice 这里要说明一下,如果你使用的是路径,比如slice2cpp d:\TestICE.ice 这样是可以的,但是如果路径中有中文,会报错。

如果一切顺利,你将会在你的*.ice路径下得到两个文件,一个.h一个.cpp。其实感觉,如果你能仔细分析懂这些代码,弄个模板自己改一个也行,不需要ICE帮你生成,当然,简单起见,还是ICE的工具比较方便,毕竟可以帮你检查语法。

有了这两个文件,直接拷贝到你的Server和Client工程中,这两个都需要用。

然后写一个类,继承这个接口的虚类。

 #include "Ice/Ice.h"

#include "TestICE.h"
#include 
<string>
using namespace std;
using namespace Test;
class CTest : public TestICE
{
public:   
    
int ping(const Ice::Current&);    
    
int GetTime(string& strTime, const Ice::Current&);
};

这样,一个ICE的接口对象,就和你的实际方法绑定成功了。实现么,呵呵,你可以自己去写啦。

然后先看看服务器的源码。

class CMainServer : public Ice::Application
{
public:
    
virtual int run(intchar*[]);
};
int CMainServer::run(int argc, char* argv[])
{
    
try        
    {
        Ice::ObjectAdapterPtr AdaptrPtr 
= communicator()->createObjectAdapter("SampleTest");                
        Ice::ObjectPtr Object 
= new CTest;                
        AdaptrPtr
->add(Object, communicator()->stringToIdentity("SampleTest"));                
        AdaptrPtr
->activate();                
        communicator()
->waitForShutdown();                
        
return EXIT_SUCCESS;        
    }        
    
catch(const Ice::Exception ex)        
    {                
        printf(
"[Main]Error = %s.\n", ex);                
        
return -1;        
    }
}
int main(int argc, char* argv[])
{        
    CMainServer app;
    app.main(argc, argv, 
"init.config");
    getchar();
    
return 0;
}

这里的代码其实挺简单的,代码基本是固定的。

你需要的是修改CMainServer::init()方法,和在你的服务器exe路径下,添加一个init.config的文件。这是一个配置文件,你可以把你的一些ICE配置参数写入这个文件。

init.config里面的内容是(这是服务器的配置文件,客户端不是这个)

SampleTest.Endpoints=tcp -p 10000

这句话的意思是,你在本机开启一个服务,IP默认是你的服务器IP,端口是10000

下面说一下init()里面在干什么

Ice::ObjectAdapterPtr AdaptrPtr = communicator()->createObjectAdapter("SampleTest");

创建了一个对象代理。命名为SampleTest,这个名字你可以随便起。(communicator()实际是一个ICE的智能指针)

Ice::ObjectPtr Object = new CTest;

你创建一个ICE指针对象,指向你的类。

AdaptrPtr->add(Object, communicator()->stringToIdentity("SampleTest"));

这句话是,将你的类指针,注册到你的AdaptrPtr对象中,并关联你的"SampleTest"。内部生成一个唯一访问码和你的类指针关联。如果你有多个类,可以这样一个个指定。

AdaptrPtr->activate();

communicator()->waitForShutdown();

return EXIT_SUCCESS;

这三句是固定的,激活你的AdaptrPtr对象,并启动ICE服务。实际上,communicator()->waitForShutdown();会接管你的主线程。

好了,就这么多代码,启动你的服务器吧,如果正常,服务器会启动并占据你的10000端口。

客户端其实也很简单。

客户端的init.config文件是:

SampleTest.Proxy=SampleTest:tcp -p 10000

如果你要指定你的服务器IP,你可以

SampleTest.Proxy=SampleTest:tcp -h XXX.XXX.XXX.XXX -p 10000

如果你有多个服务器IP地址(分布网格)

SampleTest.Proxy=SampleTest:tcp -h XXX.XXX.XXX.XXX -p 10000

                                                   -h XXX.XXX.XXX.XXX -p 10000

                                                   -h XXX.XXX.XXX.XXX -p 10000

客户端代码也不复杂。

class CMainClient : public Ice::Application
{
public:
    
virtual int run(intchar*[]);
};
int CMainClient::run(int argc, char* argv[])
{
    
try
    {
        
string strData = "I'm a freeeyes.";
        TestICEPrx testice 
= TestICEPrx::checkedCast(communicator()->propertyToProxy("SampleTest.Proxy")->ice_twoway()->ice_timeout(-1)->ice_secure(false));if(!testice)
        {
            printf(
"[CMainClient::run]testice is error.\n");
            
return EXIT_FAILURE;
        }
int nData = testice->GetTime(strData);
        printf(
"[CMainClient::run]GetTime is %d.\n", nData);return EXIT_SUCCESS;
    }
    
catch(const Ice::Exception ex)
    {
        printf(
"[Main]Error = %s.\n", ex.what());
        
return -1;
    }
}
int main(int argc, char* argv[])
{
    CMainClient app;
    app.main(argc, argv, 
"init.config");
    getchar();
    
return 0;
}

这里面大部分代码都是固定的,依然只是Init里面,需要修改一下。

TestICEPrx testice = TestICEPrx::checkedCast(communicator()->propertyToProxy("SampleTest.Proxy")->ice_twoway()->ice_timeout(-1)->ice_secure(false));

这句的代码意思是,你声明一个TestICEPrx接口类,负责从你的init.config文件中获取你的配置参数,去寻找SampleTest对应的接口对象。

if(!testice)

{

    printf("[CMainClient::run]testice is error.\n");

    return EXIT_FAILURE;

}

int nData = testice->GetTime(strData);

printf("[CMainClient::run]GetTime is %d.\n", nData);

这句代码是,如果你正确的获得了这个对象,你就可以使用这个接口里面的内容了,具体调用方法如上。

其实,基础的ICE还是很简单的,随着我自己的研究深入,希望写出更多体会,呵呵。

代码在ICE3.3.1和VS2005下测试通过。