使用ICE实现RPC简单示例03

接第01部分,本节用来说明Java语言的代码实现。

使用slice2java之后,会生成10个文件,Client与Server需要分别包含多个文件。

首先是Server端:
1、新建一个java项目,引用ice-3.6.1.jar
2、copy以下几个文件
_iIceTestDisp.java
_iIceTestOperations.java
_iIceTestOperationsNC.java
iIceTest.java
iIceTestHolder.java
3、新建一个类MyICETest,实现iIceTestDisp_接口

package com.neohope.ice.test;

import Ice.Current;

public class MyIceTest extends _iIceTestDisp {
    @Override
    public String SayHelloTo(String s, Current __current) {
        return "Hello " + s;
    }

    @Override
    public int Add(int a, int b, Current __current) {
        return a+b;
    }
}

4、新建测试类TestServer

package com.neohope.ice.test;

public class TestServer {

    public static void main(String[] args) {
        Ice.Communicator ic = null;

        //初使化
        ic = Ice.Util.initialize(args);

        //创建适配器,并指定监听端口
        Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");

        //绑定
        Ice.Object obj = new MyIceTest();
        adapter.add(obj, Ice.Util.stringToIdentity("NeoICETest"));

        //激活适配器
        adapter.activate();

        //持续监听,直到服务关闭
        ic.waitForShutdown();

        //清理
        if (ic != null) {
            try {
                ic.destroy();
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

5、编译运行

然后是Client端:
1、新建一个java项目,引用ice-3.6.1.jar
2、copy以下几个文件
Callback_iIceTest_Add.java
Callback_iIceTest_SayHelloTo.java
iIceTestPrx.java
iIceTestPrxHelper.java
iIceTestPrxHolder.java
3、新建测试类TestClient

package com.neohope.ice.test;

public class TestClient {
    public static void main(String[] args) {
        Ice.Communicator ic = null;

        //初使化
        ic = Ice.Util.initialize(args);
        Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

        //查找并获取代理接口
        iIceTestPrx client = iIceTestPrxHelper.checkedCast(obj);
        if (client == null) throw new Error("Invalid proxy");

        //调用服务端方法
        System.out.println(client.SayHelloTo("neohope"));
        System.out.println(client.Add(1, 2));

        //清理
        if (ic != null) {
            try {
                ic.destroy();
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

4、编译运行

PS:
1、不要乱修改id,如果要修改,必须全部修改
2、我调整了包名,不调整也可以

使用ICE实现RPC简单示例02

接第01部分,本节用来说明C#语言的代码实现。

使用slice2cs之后,会生成一个文件JustATest.cs,无论是Client还是Server都要包含这个文件。

首先是Server端:
1、新建一个Console项目,引用ICE程序集中的Ice.dll,项目中添加JustATest.cs文件。
2、新建一个类MyICETest,实现iIceTestDisp_接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ice;
using com.neohope.ice.test;

namespace TestICEServer
{
    class MyICETest : iIceTestDisp_
    {
        public override string SayHelloTo(string s, Current current__)
        {
            return "Hello " + s;
        }

        public override int Add(int a, int b, Current current__)
        {
            return a + b;
        }
    }
}

3、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestICEServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Ice.Communicator ic = null;

            //初使化
            ic = Ice.Util.initialize(ref args);

            //创建适配器,并指定监听端口
            Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");

            //绑定
            Ice.Object obj = new MyICETest();
            adapter.add(obj,Ice.Util.stringToIdentity("NeoICETest"));

            //激活适配器
            adapter.activate();

            //持续监听,直到服务关闭
            ic.waitForShutdown();

            //清理
            if (ic != null)
            {
                try
                {
                    ic.destroy();
                }
                catch (Exception e)
                {
                }
            }
        }
    }
}

4、编译运行

然后是Client端:
1、新建一个Console项目,引用ICE程序集中的Ice.dll,项目中添加JustATest.cs文件。
2、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using com.neohope.ice.test;
//using JustATest;

namespace TestICE
{
    class Program
    {
        static void Main(string[] args)
        {
            Ice.Communicator ic = null;

            try
            {
                //初使化 
                ic = Ice.Util.initialize(ref args);
                Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

                //查找并获取代理接口
                iIceTestPrx client = iIceTestPrxHelper.checkedCast(obj);
                if (client == null)
                {
                    throw new ApplicationException("Invalid proxy");
                }

                //调用服务端方法
                Console.WriteLine(client.SayHelloTo("neohope"));
                Console.WriteLine(client.Add(1, 2));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                //清理
                if (ic != null)
                {
                    try
                    {
                        ic.destroy();
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e);
                    }
                }
            }
        }
    }
}

3、编译运行

PS:
1、不要乱修改id,如果要修改,必须全部修改
2、我调整了包名,不调整也可以

使用ICE实现RPC简单示例01

看一眼下面的框架,你就会发现,ICE框架其实与CORBA很相似。但ICE更加的简洁高效,并增加了很多现代框架的特性。同时,其开发组件更加易用,不需每种语言单独下载,学习成本相对较低。

Ice_Client_and_Server_Structure

ICE是典型CS架构,与CORBA相同,ICE帮我们处理的底层的网络通信及服务定位,我们只需要告诉ICE服务在哪里,需要哪个服务,调用参数是什么,然后就坐等处理结果就好咯。

使用ICE的时候,首先要先下载ICE的开发包,下载后直接解压就好了。
ICE下载地址

在使用ICE的时候,首先要用Slice语言,定义一个接口描述文件,比如我自己写了一个很简单的接口。
JustATest.ice

module JustATest
{ 
  interface iIceTest
  { 
    string SayHelloTo(string s);
    int Add(int a, int b);
  }; 
};

然后用对应语言的转化工具,将接口描述文件,转化为对应语言。

#设置环境变量
set ICE_HOME=C:\NeoArch\ZeroC\Ice-3.6.1
set PATH=%ICE_HOME%\bin;%PATH%

#转化为java
slice2java JustATest.ice

#转化为csharp
slice2cs JustATest.ice

那ICE的Client端,是如何找到Server,并告诉Server要调用哪个服务的呢?

//首先,Server在启动的时候,要指定Adapter的名称与端口
ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");
//然后,在Server端的Adapter上,要做一个类似于将服务名称与服务对象绑定的动作
adapter.add(obj,Ice.Util.stringToIdentity("NeoICETest"));

//当Client启动的时候,要指定端口及服务名称,这样就找到了
Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

那如果两个服务同名,只是端口不一致咋办呢?
你可以发现,无论是Client还是Server,无论是C#还是Java,都有类似的代码,你懂的。

        //C#
        public static readonly string[] ids__ =
        {
            "::Ice::Object",
            "::JustATest::iIceTest"
        };
    //java
    public static final String[] __ids =
    {
        "::Ice::Object",
        "::JustATest::iIceTest"
    };

在client段调用的时候,有checkedCast和uncheckedCast两种转换方式,说白了,checkedCast会先校验接口是否匹配,而uncheckedCast会直接强制转换不做任何校验。可以根据实际情况选用咯。