ICE通信之IceBox服务器
一、 简介
IceBox服务器用于配置服务、并把对它们的管理集中在一起,服务被开发成可动态加载的组件,通过属性为IceBox服务配置它负责加载和管理的应用特有的服务。要把多个服务组合成一个应用,可以通过配置、而不是编译和链接来完成。这解除了服务和服务器的耦合,允许你按照需要组合服务或分离服务。
二、 服务管理器
除了应用服务所支持的对象,IceBox服务器还支持一个实现了IceBox.ServiceManager接口的管理对象。这个对象负责加载和初始化服务,并执行客户所要求的管理动作。为了保护这个对象的端点,不让它们受到未经授权的访问,IceBox服务器还会为这个对象创建一个对象适配器。目前,ServiceManager接口的管理能力相当有限:该接口只支持shutdown,用于终止服务、关闭IceBox服务器。
三、 端点配置
服务管理器的对象适配器的端点是用IceBox.ServiceManager.Endpoints配置属性定义的:IceBox.ServiceManager.Endpoints=tcp -p 10000因为有恶意的客户可能会向服务管理器发动 “拒绝服务”攻击,明智的做法是使用SSL端点,或用适当的防火墙配置来保护这些端点,或者两者都使用。
四、 客户配置
需要访问服务管理器的管理功能的客户可以使用属性所定义的端点来创建代理。服务管理器对象的缺省标识是ServiceManager,但你可以使用IceBox.ServiceManager.Identity属性来改变它。因此,使用缺省标识和端点的代理可以构造如下:
ServiceManager.Proxy=ServiceManager:tcp -p 10000
五、 开发服务
要编写IceBox服务,需要实现某个IceBox服务接口。下面给出的Java例子实现了IceBox.Service:
module IceBox {
local interface ServiceBase {
void stop();
};
local interface Service extends ServiceBase {
void start(string name,Ice.Communicator communicator,Ice.StringSeq args)throws FailureException;
};
};
你可以看到,服务只需实现两个操作:start和stop。这些操作由服务管理器调用;start在服务加载后被调用,而stop在服务关闭时被调用。服务可以在start操作中初始化自身;这通常包括创建对象适配器和servant。name和args参数提供了来自服务的配置的信息,而communicator参数是服务管理器为供服务使用而创建的Ice.Communicator对象。取决于服务的配置,这个通信器实例可能会由同一个IceBox服务器中的其他服务共享,因此,你需要注意确保像对象适配器这样的对象的名字是唯一的。
stop操作必须回收服务所使用的任何资源。一般而言,服务会解除其对象适配器的激活,可能还需要调用对象适配器的waitForDeactivate,以确保在继续进行清理之前,所有待处理的请求都已完成。服务管理器会负责销毁通信器,缺省的行为是为每个服务创建一个新通信器。
由于下面的原因,这些接口被声明为local接口:它们代表的是服务管理器和服务之间的合约,而不是要供远地客户使用。服务与远地客户进行的任何交互都要通过服务所创建的servant来完成。
在myeclipse中创建一个java工程IceboxDemo,在工程下创建包icebox.client(存放客户端文件)、icebox.demo.slice2java(存放由slice2java命令编译生成的文件)、icebox.servant(存放servant文件)、icebox.service(存放服务)
编写Hello.ice文件,将Hello.ice文件直接存放src目录下。
#ifndef HELLO_ICE
#define HELLO_ICE
[["java:package:icebox.demo"]]
module slice2java
{
interface Hello
{
void sayHello();
};
};
#endif
打开终端,进入Hello.ice文件所在的目录,使用命令slice2java编译Hello.ice文件。
编译之后的生成的文件存放到IceboxDemo项目下的包icebox.demo.slice2java中。
六、 编写servant
Servant类名为HelloI,只是简单的实现“Hello World!”的打印功能。
package icebox.servant;
import icebox.demo.slice2java._HelloDisp;
public class HelloI extends _HelloDisp
{
public void sayHello(Ice.Current current)
{
System.out.println("Hello World!");
}
}
七、 Java实现服务
我们的服务的类定义如下,存放在icebox.service包中。
package icebox.service;
import icebox.servant.HelloI;
public class HelloServiceI extends Ice.LocalObjectImpl implements
IceBox.Service {
public void start(String name, Ice.Communicator communicator, String[] args) {
for(int i = 0;i<args.length;i++){
System.out.println("args["+i+"]="+args[i]);
}
_adapter = communicator.createObjectAdapter(name);
_adapter.add(new HelloI(), communicator.stringToIdentity("Hello"));
_adapter.activate();
}
public void stop() {
_adapter.deactivate();
}
private Ice.ObjectAdapter _adapter;
}
首先要注意,我们的类扩展了Ice.LocalObjectImpl。这是Ice开发者必须实现本地接口的极少数情况之一(其他常见的情况是对象工厂和servant定位器)。start方法用和服务名相同的名字创建一个对象适配器,激活一个类型为HelloI的servant,并激活对象适配器。stop简单地解除对象适配器的激活。
服务管理器要求服务的实现拥有缺省构造器。这是Java IceBox服务的进入点;也就是说,服务管理器会动态加载服务实现类,并调用构造器来获取服务的实例。
八、 编写客户端
客户端类名为Client,存放在icebox.client包中。
package icebox.client;
import icebox.demo.slice2java.*;
public class Client {
public static void main(String[] args) {
int status = 0;
Ice.Communicator ic = null;
try {
//初使化
ic = Ice.Util.initialize(args);
//传入远程服务单元的名称、网络协议、IP及端口,获取Hello的远程代理,这里使用的stringToProxy方式
Ice.ObjectPrx base = ic.stringToProxy("Hello:tcp -p 10000");
//通过checkedCast向下转换,获取Hello接口的远程,并同时检测根据传入的名称获取的服务单元是否Hello的代理接口,如果不是则返回null对象
HelloPrx printer = HelloPrxHelper.checkedCast(base);
if (printer == null) throw new Error("Invalid proxy");
//调用服务端HelloI打印出来,因为这个方法最终会在服务端上执行
printer.sayHello();
} catch (Ice.LocalException e) {
e.printStackTrace();
status = 1;
} catch (Exception e) {
System.err.println(e.getMessage());
status = 1;
}
if (ic != null) {
// Clean up
//
try {
ic.destroy();
} catch (Exception e) {
System.err.println(e.getMessage());
status = 1;
}
}
System.exit(status);
}
}
九、 配置服务器
要把服务配置进IceBox服务器中,只需使用一个属性。这个属性的用途有好几个:它定义服务的名字,它向服务管理器提供服务进入点,它还定义用于服务的属性和参数。下面是这个属性的格式:
IceBox.Service.name=entry_point [args]
属性键的name部分是服务名。这个名字会传给服务的start操作,在配置进同一个IceBox服务器的所有服务中必须是唯一的。用不同的名字加载同一个服务的两个或多个实例是可能的,尽管你很少需要这么做。属性值的第一个参数用于指定进入点。
对于Java服务,进入点就是服务实现类的完整类名 (包括任何package)。这个类必须位于IceBox服务器的类路径上。跟在entry_point后面的任何参数都会被检查。如果某个参数的形式是--name=value,它就会被解释为属性定义,将会出现在传给服务的start操作的通信器的属性集中。这些参数将被移除,剩下的参数会放在args参数中传给start操作。
将配置文件直接存放在src目录下,文件名为config.icebox,完整的配置文件内容如下:
IceBox.InstanceName=DemoIceBox
# The IceBox server endpoint configuration
IceBox.ServiceManager.Endpoints=tcp -p 9998
# The hello service
#创建一个名为Hello的服务,这个服务应当位于icebox.service包中的HelloServiceI类
IceBox.Service.Hello=icebox.service.HelloServiceI --Ice.Trace.Network=1 hello there
# The server creates one single object adapter with the name of
# the service. The following line sets the endpoints for this
# adapter.
Hello.Endpoints=tcp -p 10000:udp -p 10000
# Warn about connection exceptions
#
Ice.Warn.Connections=1
IceBox.Service.Hello=icebox.service.HelloServiceI --Ice.Trace.Network=1 hello there,使用这个配置,将会创建一个名为Hello的服务。这个服务应当位于icebox.service.HelloServiceI类中。参数--Ice.Trace.Network=1(网络跟踪级别,1代表跟踪连接的建立和关闭)被转换成属性定义,交给start方法中的Communicator通信器处理,参数hello和there则会成为传给start方法的args序列参数中的两个元素,参数在此文章的例子中没有作用。
完成的目录结构如下:
十、 共享一个通信器
你可以用下面的属性对服务管理器进行配置,让它的所有服务共享一个
通信器实例:IceBox.UseSharedCommunicator=1
如果没有定义这个属性,缺省的行为是为每个服务创建一个新通信器。但是,如果你想要对服务进行并置优化,就必须使用一个共享的通信器实例。
十一、 加载服务
在缺省情况下,服务管理器加载服务的次序是不确定的,也就是说,同一个IceBox服务器中的各个服务不应该相互依赖。如果多个服务必须按照特定的次序加载,可以使用IceBox.LoadOrder属性:
IceBox.LoadOrder=Service1,Service2
在这个例子中,Service1首先加载,接着是Service2。剩下的其他服务在Service2之后以不确定的次序加载。在IceBox.LoadOrder中提到的每个服务都必须有相匹配的IceBox.Service属性。
十二、 运行客户和服务器
1.1. 运行IceBox服务器
把我们在前面讨论的内容结合在一起,我们现在可以配置并启动IceBox服务器了。
进入点的指定:
IceBox.ServiceManager.Endpoints=tcp -p 9998 IceBox.Service.Hello= icebox.service.HelloServiceI Hello.Endpoints=tcp -p 10000 |
我们已经将这些属性写入config.icebox的配置文件中,我们可以使用类似这样命令启动Java IceBox服务器:
$ java IceBox.Server --Ice.Config= config.icebox |
IceBox.Server是IceBox服务器的主类,该类位于Ice.jar包中,所以执行该命令时,classpath环境变量必须指定Ice.jar包所在位置。
config.icebox是启动IceBox服务器所需要的配置,我们已经存放在java工程IceboxDemo的src目录下。
1、首先打开一个命令行终端,进入config.icebox配置文件存放的目录下,如下图:
此处的路径并不是我们前面提到IceboxDemo工程的src目录下,而是myeclipse编译源文件之后的class文件所在的bin目录下,bin目录下存放的是项目所有的class文件和配置文件。
2、执行以下命令
java -classpath .;F:\lhy_workspace\IceboxDemo\bin\Ice.jar IceBox.Server --Ice.Config=config.icebox |
执行完成以后,如下图所示:
以上大部分信息都是网络跟踪日志信息。
1.2. 运行客户端
在myeclipse中运行Client客户端,
终端打印出“Hello World!”信息。
参考《Ice分布式程序设计》马维达 译.
ICE通信之IceBox服务器相关推荐
- 详细教你如何部署ICE服务(二)---IceBox加载启动Ice服务
在上一篇文章中,我使用了自己实现的一个简单容器简单粗暴的启动一个ICE服务,正如上篇文章所总结的那样,这种部署服务的方式存在诸多缺点. 这里我们给出使用IceBox这个框架来开发和部署我们的Ice服务 ...
- 详细教你如何部署ICE服务(三)---IceBox框架 Ice Registry服务注册中心的联合使用
在详细教你如何部署ICE服务(二)---IceBox加载启动Ice服务这篇博客中,我们使用了IceBox来设计服务代码和启动Ice服务. 单单使用IceBox组件来设计和启动Ice服务,客户端必须将服 ...
- Epoll 的tcp通信代码(服务器+客户端)
http://blog.csdn.net/libinbin_1014/article/details/50096187 Epoll 的tcp通信代码(服务器+客户端) /* gcc -D_LARGEF ...
- qt与JAVA服务器通信_Qt实现的SSL通信客户端和服务器
[实例简介] Qt实现的SSL通信客户端和服务器 使用QSslSocket实现加密通信 [实例截图] [核心代码] f3a25e44-604e-4435-9e05-3f6efe57c6b0 └── s ...
- 什么是阿里云Intel Xeon(Ice Lake) Platinum 8369B服务器?
什么是阿里云Intel Xeon(Ice Lake) Platinum 8369B服务器?阿里云服务器CPU处理器Intel Xeon(Ice Lake) Platinum 8369B,基频2.7 G ...
- Zeroc Ice 学习笔记--IceBox
Zeroc Ice 学习笔记--IceBox 1.介绍 IceBox就好像是一个Tomcat,只需要服务实现Ice.Server接口并能轻松搞定 2.案例(参考Zeroc Ice 权威指南) ice文 ...
- python 实现TCP socket通信和 HTTP服务器、服务器和客户端通信python实例
python 实现TCP socket通信和 HTTP服务器.服务器和客户端通信实例 socket是什么? 服务器和客户端通信的流程 python 实现TCP socket通信例子 关于Host和PO ...
- RPC 笔记(05)— socket 通信(单线程服务器)
1. Python 标准库 1.1 socket 提供 RPC 服务的网络通信功能,方便用户编写 tcp/udp 相关的代码.两个不同机器的进程需要通信时,可以通过 socket 来传输数据. 客 ...
- flash java 通信_FLASH与服务器通讯 (JAVA)
1.FLASH 通过URL地址获得服务器数据. 这种方式最为简单,就像在浏览器的地址栏里面敲一样. 先建立一个URLRequest,然后用URLLoader载入就行了. 下面这个是载入一个图片,htm ...
最新文章
- 制作欧比旺·克诺比逼真的CG角色学习教程
- 如何修改python代码,如何更改默认的python版本?
- Flask-sqlalchemy外键关系映射
- 18-ESP8266 SDK开发基础入门篇--TCP 服务器 RTOS版,串口透传,TCP客户端控制LED
- Leetcode--23.合并K个排序链表(Java)
- 整理好的200多java面试题,可用于机器学习
- 就知道你会没灵感,感恩节psd分层海报模板来咯!
- STL(1)——查找函数find的使用
- JavaScript学习(八十九)—数组练习题
- Go 语言——基本类型
- 日常开发中linux中最常用的100条命令
- mysql错误:Found option without preceding group in config file
- sencha app watch php,Sencha Cmd使用指南
- cdc有哪些rapper_CDC说唱会馆在圈内是一个什么样的存在
- 那些酷炫的深度学习网络图怎么画出来的?
- 改变ubutun 默认配色
- 混合多云时代下的传统灾备VS云灾备
- 怎么用CSS实现三角形?
- Python提取Word中的图片
- ps国画效果案例制作教程和思路介绍