1、ice文件
#include <Ice/Identity.ice>
module ServiceModule{
// 建立连接结构
class IConnectInfo {
["cpp:type:wstring"]
string ID;
};
class IReturnInfo {
// 是否成功
bool IsSuccess;
// 信息
["cpp:type:wstring"]
string Info;
};
/*客户端实现 */
interface PublishClient {
// 控制
IReturnInfo Control(string type);
};
/* 服务端实现 */
interface PublishServer {
// 1.0建立连接
IReturnInfo ConnectToServer(Ice::Identity ident, IConnectInfo info);
};
};
2、IceApplication.cs
public class IceApplication : Ice.Application
{
private static PublishServerPrx _iceServicePrx = null;
private ObjectPrx _objectPrx;
private Identity _ident = null;
//对象适配器(Ice::ObjectAdapter)对象适配器负责提供一个或多个传输端点,并且把进入的请求分派到对应的servant中去执行
private ObjectAdapter _adapter = null;
//重连间隔
public const int ReConnectInterval = 6000;
public bool IsStop = true;
public static string identity = "1";
//连接状态
public bool isConnectIce = false;
//连接信息
private IConnectInfo _connInfo = null;
public PublishServerPrx GetServerPrx
{
get { return _iceServicePrx; }
}
public override int run(string[] args)
{
Start();
return 1;
}
/// <summary>
/// 开始
/// </summary>
public void Start()
{
IConnectInfo info = new IConnectInfo
{
ID="1"
};
try
{
/*
* Ice::Communicator:通讯器
* 通讯器管理着线程池、配置属性、对象工厂、日志记录、统计对象、路由器、定位器、插件管理器、对象适配器。
* Ice::ObjectPrx propertyToProxy(const std::string&) const;
* 这个方法根据给定的名字的属性配置生成一个代理对象,如果没有对应属性,返回一个空代理。
* 比如有如下属性:
* MyApp.Proxy = ident:tcp -p 5000
* 我们就可以这样得到它的代理对象:
* Ice::ObjectPrx p = communicator->propertyToProxy("MyApp.Proxy"); --对应config.client文件中的属性名称
* Ice::ObjectAdapterPtr createObjectAdapter(const std::string&);
* Ice::ObjectAdapterPtr createObjectAdapterWithEndpoints(const std::string&, const std::string&);
* 这两个方法创建新的对象适配器。createObjectAdapter从属性配置中取得端点信息,而 createObjectAdapterWithEndpoints则直接指定端点。
* 对象代理(Object Proxy)
* 在客户端,我们使用对象代理进行远程调用,就如它们就在本地一样。
* 但有时,网络问题还是要考虑的,于是Ice的对象代理提供了几个包装方法,以支持一些 网络特性:
* ice_timeout方法,声明为:Ice::ObjectPrx ice_timeout(int) const;
* 返回一个超时代理,当在指定的 时间(单位毫秒)内没有得到服务器端响应时,操作终止并抛出Ice::TimeoutException异常。
*
* ice_oneway方法,声明为:Ice::ObjectPrx ice_oneway() const;返回一个单向调用代理。
* 只要数据从本地 端口发送出去,单向调用代理就认为已经调用成功。
* 这意味着,单向调用是不可靠的:它可能根本没有发送出去 (例如,因为网络故障) ,也可能没有被服务器接受(例如,因为目标对象不存在)。
* 好处是由于不用等服务端回复,能带来很大的效率提升。
* */
// 取得服务代理
_objectPrx = communicator()
.propertyToProxy("CallbackSender.Proxy")
.ice_twoway()
.ice_timeout(-1)
.ice_secure(false);
//通过checkedCast向下转换,获取Printer接口的远程,并同时检测根据传入的名称获取的服务单元是否Printer的代理接口,如果不是则返回null对象
_iceServicePrx = PublishServerPrxHelper.checkedCast(this._objectPrx);
IceReceiver sender = new IceReceiver();
//创建适配器
this._adapter = this.CreateAdapter(sender, this._ident);
//激活适配器
this._adapter.activate();
_iceServicePrx.ice_getConnection().setAdapter(this._adapter);
IReturnInfo connInfo = _iceServicePrx.ConnectToServer(this._ident,info);
if (connInfo.IsSuccess)
{
isConnectIce = true;
Console.WriteLine("ice连接成功。");
}
while (!IsStop)
{
Thread.Sleep(IceApplication.ReConnectInterval);
}
}
catch (System.Exception ex)
{
throw;
}
}
/// <summary>
/// ICE服务重新连接
/// </summary>
public void IceReconnet()
{
try
{
IConnectInfo stationinfo = new IConnectInfo
{
ID = "1",
};
_iceServicePrx.ice_getConnection().setAdapter(this._adapter);
IReturnInfo info = _iceServicePrx.ConnectToServer(this._ident, stationinfo);
if (info.IsSuccess == true)
{
isConnectIce = true;
Console.WriteLine("重连成功!");
}
}
catch (Ice.Exception ex)
{
isConnectIce = false;
Console.WriteLine("重连失败!");
}
}
/// <summary>
/// ping
/// </summary>
/// <returns></returns>
public bool IsPingOK()
{
bool isPingOK = false;
try
{
GetServerPrx.ice_ping();
isPingOK = true;
}
catch (System.Exception ex)
{
Console.WriteLine("ice服务端ping异常"+ex.ToString());
isConnectIce = false;
isPingOK = false;
}
return isPingOK;
}
/// <summary>
/// 创建适配器
/// </summary>
/// <param name="serv"></param>
/// <param name="ident"></param>
public ObjectAdapter CreateAdapter(Ice.Object serv,Identity ident)
{
ObjectAdapter adapter = communicator().createObjectAdapter("");
this._connInfo = this.CreateInfo(5);
this._ident = this.CreateIdentity(identity, "");
adapter.add(serv, _ident);
return adapter;
}
/// <summary>
/// IConnectInfo构建
/// </summary>
/// <param name="stationID"></param>
/// <returns></returns>
private IConnectInfo CreateInfo(int stationID)
{
var info = new IConnectInfo()
{
ID= stationID.ToString()
};
return info;
}
/// <summary>
/// 创建身份
/// </summary>
/// <param name="name"></param>
/// <param name="category"></param>
/// <returns></returns>
private Identity CreateIdentity(string name, string category)
{
return new Identity(name, category);
}
}
3、实现接口。类名为:IceReceiver.cs
public class IceReceiver : ServiceModule.PublishClientDisp_
{
public override IReturnInfo Control(string type, Current current__)
{
throw new NotImplementedException();
}
}
4、余下实现
class Program
{
public static IceClient client = new IceClient();
public static int IceReConnectTime = 5;//ice重连时间间隔5s
static void Main(string[] args)
{
Thread tdMain = new Thread(BeginService);
tdMain.Start();
Console.ReadKey();
}
/// <summary>
/// 开户连接服务
/// </summary>
private static void BeginService()
{
try
{
//连接ice
client.Run();
//开启ice重连机制
Thread tdIceReConnect = new Thread(IceReconnect);
tdIceReConnect.Start();
}
catch (Exception ex)
{
Console.WriteLine("连接异常!"+ex.ToString());
}
}
/// <summary>
/// ICE重连服务
/// </summary>
private static void IceReconnect()
{
while (true)
{
Thread.Sleep(IceReConnectTime * 1000);
if (client.app.GetServerPrx == null)
{
client.Run();
}
else
{
bool isPingOK = client.app.IsPingOK();
if (isPingOK && !client.app.isConnectIce)
{
client.app.IceReconnet();
}
}
}
}
}
public class IceClient
{
public IceApplication app = new IceApplication();
public void Run()
{
Thread t = new Thread(new ThreadStart(start));
t.Start();
}
private void start()
{
app.IsStop = false;
//ice配置文件
string cfg = AppDomain.CurrentDomain.BaseDirectory + "config.client";
app.main(new string[] { }, cfg);
}
}
5、config.client
6、参考
http://blog.chinaunix.net/uid-126438-id-2924656.html