如上图所述,我们所要做的工作就是将一台客户端发出的信息,广播到其它的客户端上,就是这么一个简单的操作。为了达到这种目的,必须在服务器端和客户端都开一个监听端口,用来双方交互,同时服务器端还要接受客户端的请求,成为一个信息HUB。
因为ICE本身就是平台无关的,所以在什么平台上编缉并不影响其它平台。首先要写一个slice文件,定义服务。
module FloorSpace
{
interface CallBack
{
void GetInput(string content);
};
dictionary<string,CallBack *> CacheMap;
interface Floor
{
bool Register(string name);
void SetInput(string content);
void Unregister();
void SetupCallback(CallBack * cp);
};
};
CallBack是用来定义客户端的回调服务,Floor是用来定义服务器端的服务。
定义好slice文件后,比如叫做floor.ice,用slice2cpp floor.ice生成服务。它会生成floor.h 和floor.cpp两个文件,这两个文件定了服务接口和代理接口。
需要一个文件用来从floor.h中继承Floor接口中的各种服务,需要一个文件用来从floor.h中继承CallBack接口中的服务。
class FloorI:virtual public Floor
{
virtual bool Register(const string & name,const Current & context);
virtual void SetInput(const string & content,const Current & context);
virtual void Unregister(const Current & context);
virtual void SetupCallback(const CallBackPrx & prx,const Current & context);
CacheMap m_cache_map;
};
class CallBackI:virtual public CallBack
{
public:
virtual void GetInput(const string & content,const Current & context);
};
当然需要将FloorI中的虚函数实现,这就是你的服务真正所在了。
bool FloorI::Register(const string & name,const Current & context)
{
if(m_cache_map.find(name)!=m_cache_map.end())
return 0;
else
m_cache_map[name];
return 1;
}
void FloorI::Unregister(const Current & context)
{
Context::const_iterator q=context.ctx.find("user_name");
if(q!=context.ctx.end())
{
CacheMap::iterator p;
if((p=m_cache_map.find(q->second))!=m_cache_map.end())
m_cache_map.erase(p);
}
}
void FloorI::SetupCallback(const CallBackPrx & prx,const Current & context)
{
Context::const_iterator p=context.ctx.find("user_name");
if(p!=context.ctx.end())
{
m_cache_map[p->second]=prx;
}
}
void FloorI::SetInput(const string & content,const Current & context)
{
Context::const_iterator q=context.ctx.find("user_name");
if(q!=context.ctx.end())
{
CacheMap::iterator p;
for(p=m_cache_map.begin();p!=m_cache_map.end();++p)
{
if(p->first!=q->second)
{
Context ctx;
ctx["user_name"]=q->second;
try
{
p->second->GetInput(content,ctx);
}
catch(ConnectionRefusedException e)
{
m_cache_map.erase(p);
cout<<" 挂了"<<endl;
}
catch(NullHandleException e)
{
m_cache_map.erase(p);
cout<<" 没有诚意"<<endl;
}
}
}
}
}
CallBack服务具体定义:
void CallBackI::GetInput(const string & content,const Current & context)
{
Context::const_iterator q=context.ctx.find("user_name");
if(q!=context.ctx.end())
{
cout<<"["<<q->second<<" say]"<<content<<endl;
}
}
这样我们的聊天室服务器端和客户端的服务定义实现完毕。剩下就是写服务器和客户端了,服务器的实现很简单,因为这是ICE的框架:
int ServerApp::run(int argc,char * argv[])
{
shutdownOnInterrupt();
ObjectAdapterPtr adapter=communicator()->createObjectAdapter("Floor.Server");
adapter->add(new FloorI,stringToIdentity("floor"));
adapter->activate();
communicator()->waitForShutdown();
return EXIT_SUCCESS;
}
就这么几行代码,可以实现网络联结和服务创建。客户端的实现:
int ClientApp::run(int argc,char * argv[])
{
shutdownOnInterrupt();
Ice::PropertiesPtr properties = communicator()->getProperties();
const char * buf="Floor.Proxy";
string proxy=properties->getProperty(buf);
if(proxy.empty())
{
cerr << argv[0] << ": property `" << buf << "' not set" << endl;
return EXIT_FAILURE;
}
cout<<proxy<<endl;
FloorPrx floorprx=FloorPrx::checkedCast(communicator()->stringToProxy(proxy));
if(!floorprx)
{
cerr << argv[0] << ": invalid proxy" << endl;
return EXIT_FAILURE;
}
string user_name;
cout<<"name : ";
cin>>user_name;
cout<<endl;
if(floorprx->Register(user_name)==0)
{
cout<<user_name<<" has been registered"<<endl;
return EXIT_FAILURE;
}
Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Floor.Client");
adapter->add(new CallBackI, Ice::stringToIdentity("callbackReceiver"));
adapter->activate();
Context ctx;
ctx["user_name"]=user_name;
floorprx=FloorPrx::uncheckedCast(floorprx->ice_newContext(ctx));
CallBackPrx cbp=CallBackPrx::uncheckedCast(adapter->createProxy(stringToIdentity("callbackReceiver")));
floorprx->SetupCallback(cbp);
string content;
cout<<"please input something"<<endl;
cout<<"["<<user_name<<" say]";
while(cin>>content)
{
cout<<endl;
floorprx->SetInput(content);
cout<<"["<<user_name<<" say]";
}
floorprx->Unregister();
}
实现的就是一个人说话,将他说的话传到服务器,服务器将其广播到其它用户,功能实现完毕。
总结:ICE使你不用关心网络如何联结,端口如何定义,你所要关心的就是服务如何实现,而这正是你想要的。当你知道想做什么,但一想到网络通讯的复杂程度,可能就没有信心了,ICE正好使它成为可能。学习ICE是一件很愉快的事。
 |
文件: | ice_floor_callback.rar | 大小: | 10KB | 下载: | 下载 | |