在项目中,往往很多时候涉及全双工通信要求,zeroc-ice样例介绍很多异步通信的策略,
但我最近项目需求中,不仅是要全双工通信,还要求服务端需要明确每个客户端及区别对待,
所以需要给每个客户端做标记处理
1)ice定义
#pragma once
#include <Ice/Identity.ice>
module TestIce
{
struct DateTimeI {
int isec;
int imsec;
};
interface ClientAchieve
{
//客户端实现
void PValueChange_A(long devID,long pID, DateTimeI itime, float val);//A类客户端实现
void PValueChange_B(long devID,long pID, DateTimeI itime, float val);//B类客户端实现
};
interface ServerAchieve
{
//服务端实现
void AddClient(::Ice::Identity ident, int ctype);
void setPValue(long devID, long pID, float val);
};
};
2)接口实现:
在我的ice定义中
void AddClient(::Ice::Identity ident, int ctype);是很关键的一项,该函数是有服务端实现,
在客户端链接成功将其识别号及类型告知服务端,服务端将进行标记,该逻辑过程如下:
客户端链接及通告服务端代码样例
Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("");
Ice::Identity ident;
ident.name = IceUtil::generateUUID();
m_strUUID = ident.name;
ident.category = "";
ClientAchievePtr crtwoway = new ClientAchieveI(this);
adapter->add(crtwoway, ident);
adapter->activate();
soneway->ice_getConnection()->setAdapter(adapter);
soneway->AddClient(ident,ctype);//通知服务端
而在服务端,我们将进行标记每个客户端,示例代码:
void ServerAchieveI::AddClient(const ::Ice::Identity& ident,const ::Ice::Int &ctype, const ::Ice::Current& current)
{
printf("adding client `%s(%d)'\n", _communicator->identityToString(ident).c_str(),ctype);
TestIce::ClientAchievePrx client = PCS::ClientAchievePrx::uncheckedCast(current.con->createProxy(ident));
//clients定义了一个客户端管理类,采用std::map<TestIce::ClientAchievePrx, ClientFlag> _clients;进行客户端标记
clients->addCLient(client,ctype);
};
现在我们展示服务端接口代码示例:
class ClientManageThread;
class ServerAchieveI : public TestIce::ServerAchieve
{
public:
ServerAchieveI(const Ice::CommunicatorPtr& communicator);
virtual ~ServerAchieveI();
//
virtual void AddClient(const ::Ice::Identity&, const ::Ice::Int &ctype,const ::Ice::Current& = ::Ice::Current());
virtual void setPValue(::Ice::Long devID, ::Ice::Long pID, float val, const ::Ice::Current&);
private:
// Required to prevent compiler warnings with MSVC++
ServerAchieveI& operator=(const ServerAchieveI&);
Ice::CommunicatorPtr _communicator;
ClientManageThread *clients;
};
/////////////////////////////////////
ServerAchieveI::ServerAchieveI(const Ice::CommunicatorPtr& communicator)
: _communicator(communicator)
{
clients = new ClientManageThread();
clients->start();
};
ServerAchieveI::~ServerAchieveI()
{
try
{
delete clients;
clients = NULL;
}
catch (...)
{
}
};
void ServerAchieveI::AddClient(const ::Ice::Identity& ident, const ::Ice::Int &ctype,const ::Ice::Current& current)
{
printf("adding client `%s(%d)'\n", _communicator->identityToString(ident).c_str(),ctype);
TestIce::ClientAchievePrx client = TestIce::ClientAchievePrx::uncheckedCast(current.con->createProxy(ident));
clients->addCLient(client,ctype);//clients根据ctype类型调用TestIce::ClientAchievePrx的客户端实现函数发送数据到指定客户端
};
//客户端调用该函数实现客户端到服务端的数据发送,soneway->setPValue(devID,pID,val);
void ServerAchieveI::setPValue(::Ice::Long devID, ::Ice::Long pID, float val, const ::Ice::Current& )
{
std::cerr << " setPValue:"<< devID<<","<<pID<<","<<val << std::endl;
PFrom _pfrom;
};
展示客户端代码样例,例如该客户端只需实现A类型函数:
///////////////////////////////h////////////////////////////////////////////////////////////////
class TestIceClient;
class ClientAchieveI : public TestIce::ClientAchieve
{
public:
ClientAchieveI(TestIceClient* _client);
~ClientAchieveI();
virtual void PValueChange_A(::Ice::Long devID
,::Ice::Long pID
, const ::TestIce::DateTimeI& itime
, ::Ice::Float val
, const ::Ice::Current&);
private:
TestIceClient* client;//真正实现类
};
/////////////////////////////////////////////cpp/////////////////////////////////////
ClientAchieveI::ClientAchieveI(TestIceClient* _client) : client(_client)
{
};
ClientAchieveI::~ClientAchieveI()
{
};
void ClientAchieveI::PValueChange(::Ice::Long devID
,::Ice::Long pID
, const ::TestIce::DateTimeI& itime
, ::Ice::Float val
, const ::Ice::Current&)
{
std::cerr <<" PValueChange:" <<devID<<","<<pID<<","<<val<<","<<itime.isec<<","<<itime.imsec<< std::endl;
if(client)
client->PValueChange(devID,pID,itime,val);
};
3)实现调用示例:
在我的ClientManageThread类中,实现数据从服务端发送各客户端:
mutex_client.Lock();
std::map<TestIce::ClientAchievePrx, int>::iterator itw = _clients.begin();
while(itw != _clients.end())
{
try
{
switch(it->second)
{
case 1:
itw->first->PValueChange_A(wdlc.devID, wdlc.pID, _itime, wdlc.val);
break;
case 2:
itw->first->PValueChange_B(wdlc.devID, wdlc.pID, _itime, wdlc.val);
break;
default:
break;
}
itw++;
}
catch (...)
{
printf("PValueChange Error:%d\n",static_cast<int>(time(NULL)));
#ifdef WIN32
itw = _clients.erase(itw);
#else
std::map<TestIce::ClientAchievePrx, int>::iterator ittmp = itw++;
_clients.erase(ittmp);
#endif
}
}
mutex_client.Unlock();
在客户端调用与已很多zeroc-ice的demoo一致:
//TestIce::ServerAchievePrx soneway;
if(connect())
{
try{ soneway->setPValue(devID,pID,val);
}catch(...)
{
disconnect();
}
}
本文只是抛出一个zeroc-ice做全双工通信的思路,所展示代码只是具体代码中择取的代码,功能并不完善,大家可按自身需求修改完善适合自身项目诉求