6.2 基于CORBA技术的聊天软件:
本程序实现了CORBA与TUXEDO的互连,为联创系统集成软件公司的数据网综合业务计费与管理系统(LICMS)与佳都国际软件公司的飞马系统的集成打好了技术基础。
该软件的接口定义(IDL)如下:
// Chat.idl
module Chat {
typedef string User;
typedef string Time;
struct Message {
User sender;
User receiver;
Time timestamp;
string content;
};
typedef sequence<User> UserList;
typedef sequence<Message> MessageList;
interface ChatServer {
short getOnlineUsers(out UserList onlineUsers);
short getMessages(out MessageList msgList, in User regName);
short registerUser(in User regName);
short UnregisterUser(in User UnregName);
short sendMessage(in Message sendMsg);
};
};
该软件的服务器端Skeleton(骨架)定义如下:
// Server.cpp : Defines the entry point for the console application.
//
#include <iostream.h>
#include "ChatServerImpl.h"
#if defined(_VIS_STD)
# include <fstream>
#else
# include <fstream.h>
#endif
int main(int argc, char* const* argv)
{
try {
// Initialize the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Get the property manager; notice the value returned
// is not placed into a 'var' type.
VISPropertyManager_ptr pm = orb->getPropertyManager();
pm->addProperty("vbroker.se.mySe.scms", "scmlist");
pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.type", "Socket");
pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMax", (CORBA::ULong)100);
pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMaxIdle",
(CORBA::ULong)300);
pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.type", "IIOP");
// We just add the Port host will be set to NULL
// and will be filled with the default host
pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.port", (CORBA::ULong)55000);
pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.proxyPort", (CORBA::ULong)0);
pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.type",
"ThreadPool");
pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMax", (CORBA::ULong)100);
pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMin", (CORBA::ULong)5);
pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMaxIdle",
(CORBA::ULong)300);
// Get a reference to the root POA
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);
// Create the policies
CORBA::Any_var seAny(new CORBA::Any);
// The SERVER_ENGINE_POLICY_TYPE requires a sequence, even if
// only one engine is being specified.
CORBA::StringSequence_var engines = new CORBA::StringSequence(1UL);
engines->length(1UL);
engines[(CORBA::ULong)0] = CORBA::string_dup("mySe");
seAny <<= engines;
CORBA::PolicyList_var policies = new CORBA::PolicyList(2UL);
policies->length(2UL);
policies[(CORBA::ULong)0] = orb->create_policy(PortableServerExt::SERVER_ENGINE_POLICY_TYPE, seAny);
policies[(CORBA::ULong)1] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);
// get the POA Manager
PortableServer::POAManager_var poa_manager = rootPOA->the_POAManager();
// Create our POA with our policies
PortableServer::POA_var myPOA = rootPOA->create_POA("chat_server_poa",
poa_manager,
policies);
// Create the servant
ChatServerImpl managerServant;
// Decide on the ID for the servant
PortableServer::ObjectId_var managerId =
PortableServer::string_to_ObjectId("ChatServer");
// Activate the servant with the ID on myPOA
myPOA->activate_object_with_id(managerId, &managerServant);
// Obtain the reference
CORBA::Object_var ref = myPOA->servant_to_reference(&managerServant);
CORBA::String_var string_ref = orb->object_to_string(ref.in());
ofstream refFile("ref.dat");
refFile << string_ref << endl;
refFile.close();
/*
// Initialize the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// get a reference to the root POA
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(
PortableServer::PERSISTENT);
// get the POA Manager
PortableServer::POAManager_var poa_manager = rootPOA->the_POAManager();
// Create myPOA with the right policies
PortableServer::POA_var myPOA = rootPOA->create_POA("chat_server_poa",
poa_manager,
policies);
// Create the servant
ChatServerImpl managerServant;
// Decide on the ID for the servant
PortableServer::ObjectId_var managerId =
PortableServer::string_to_ObjectId("ChatServer");
// Activate the servant with the ID on myPOA
myPOA->activate_object_with_id(managerId, &managerServant);
*/
// Activate the POA manager
poa_manager->activate();
/// Wait for Incoming Requests
cout << "managerServant Server ready" << endl;
orb->run();
}
catch(const CORBA::Exception& e) {
cerr << e << endl;
return 1;
}
return 0;
}
该软件的客户端Stub(存根)定义如下:
// ORBClient.h
#if !defined corba_client_h_
#define corba_client_h_
#include "chat_c.h"
//USE_STD_NS
class corba_client{
private:
CORBA::ORB_var orb;
// PortableServer::ObjectId_var managerId;
Chat::ChatServer_var chatserver;
Chat::MessageList_var msglist;
Chat::UserList_var usrlist;
char username[40];
int osagentport;
static corba_client *_Manager;
corba_client(int port,char* name);
public:
static corba_client *GetInstance (int port,char* name);
static void destroyInstance();
~corba_client();
int corba_client::orb_init();
int getOnlineUsers();
int get_user_by_num(char * name,int message);
int getMessages();
int get_message_by_num(char * sender,char * receiver,char * timestamp,char * content,int num);
int registerUser();
int UnregisterUser();
int sendMessage(const char* sender,const char* receiver,const char* content);
};
#endif // !defined corba_client_h_
//ORBClient.cpp
#include "stdafx.h"
#include "OrbClient.h"
#include <fstream.h>
corba_client *corba_client::_Manager = 0;
corba_client::corba_client(int port,char* name){
osagentport = port;
strcpy(username,name);
}
corba_client::~corba_client(){
}
int corba_client::orb_init()
{
cout<<"begin c++ orb_init"<<endl;
int argc=3;
char* argv[3];
argv[0] = "Chat";
argv[1] = "-ORBid";
argv[2] = "BEA_IIOP";
const int MAXBUF = 1024;
char ior[MAXBUF];
try {
// Initialize the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Default to checking
CORBA::String_var fileName(CORBA::string_dup("ref.dat"));
// Convert from string to object
ifstream in(fileName);
in.getline(ior, MAXBUF);
CORBA::Object_var object = orb->string_to_object(ior);
// Locate an account manager. Give the full POA name and the servant ID.
chatserver = Chat::ChatServer::_narrow(object);
/*
orb = CORBA::ORB_init(argc,argv);
TimeBase::TimeT timeout = 20000000;
CORBA::Any timeout_value;
timeout_value <<= timeout;
CORBA::Policy_var policy;
policy = orb->create_policy(Messaging::RELATIVE_RT_TIMEOUT_POLICY_TYPE,timeout_value);
cout<<"ok 1"<<endl;
managerId = PortableServer::string_to_ObjectId("ChatServer");
cout<<"ok 2"<<endl;
chatserver = Chat::ChatServer::_bind("/chat_server_poa", managerId);
CORBA::PolicyList policies;
policies.length(1);
policies[0] = CORBA::Policy::_duplicate(policy);
CORBA::Object_var pmobj = orb->resolve_initial_references("ORBPolicyManager");
CORBA::PolicyManager_var orb_mgr = CORBA::PolicyManager::_narrow(pmobj);
orb_mgr->set_policy_overrides(policies, CORBA::SET_OVERRIDE);
cout<<"end c++ init"<<endl;
*/
}
catch(CORBA::OBJECT_NOT_EXIST& e)
{
cout << "Chat Server is not start up!" <<endl;
return -1;
}
catch (CORBA::Exception& e)
{
cout << "CORBA exception : " << e.get_id() << endl;
return -1;
}
catch(...){
cout << "There are some Unknown error while inititial ORB"<<endl;
return -1;
}
return 0;
}
corba_client * corba_client::GetInstance (int port,char* name) {
if (!_Manager)
{
_Manager = new corba_client(port,name);
#ifdef _DEBUG
cout << " new corba_client " << endl;
#endif
}
return _Manager;
}
void corba_client::destroyInstance(){
#ifdef _DEBUG
cout << " delete corba_client " << endl;
#endif
if (_Manager)
delete _Manager;
_Manager = 0;
}
int corba_client::getOnlineUsers() {
if((Chat::ChatServer_ptr)chatserver == NULL)
return -1;
int i;
try{
cout<<"start getOnlineUsers..."<<endl;
if((Chat::ChatServer_ptr)chatserver != NULL)
i=chatserver->getOnlineUsers(usrlist);
cout<<"end getOnlineUsers..."<<endl;
}
catch(CORBA::Exception &e)
{
cerr << e.get_id() << endl;
i=-2;
}
return i;
}
int corba_client::get_user_by_num(char * name,int num)
{
if (num < 0 || num > usrlist->length())
return -1;
if((Chat::ChatServer_ptr)chatserver != NULL){
Chat::UserList::_ForSeq_var* item = &((*usrlist)[num]);
strcpy(name,*item); // ??
}
return 0;
}
int corba_client::getMessages() {
if((Chat::ChatServer_ptr)chatserver == NULL)
return -1;
int i;
try{
cout<<"start getMessages..."<<endl;
if((Chat::ChatServer_ptr)chatserver != NULL)
i=chatserver->getMessages(msglist,username);
cout<<"end getMessages..."<<endl;
}
catch(CORBA::Exception &e)
{
cerr << e.get_id() << endl;
i=-2;
}
return i;
}
int corba_client::get_message_by_num(char * sender,char * receiver,char * timestamp,char * content,int num)
{
if (num < 0 || num > msglist->length())
return -1;
if((Chat::ChatServer_ptr)chatserver != NULL){
Chat::Message * item = &((*msglist)[num]);
strcpy(sender,item->sender);
strcpy(receiver,item->receiver);
strcpy(timestamp,item->timestamp);
strcpy(content,item->content);
}
return 0;
}
int corba_client::registerUser()
{
if((Chat::ChatServer_ptr)chatserver == NULL)
return -1;
int i;
try{
i=chatserver->registerUser(username);
}
catch(CORBA::Exception &e)
{
cerr << e.get_id() << endl;
i=-2;
}
return i;
}
int corba_client::UnregisterUser()
{
if((Chat::ChatServer_ptr)chatserver == NULL)
return -1;
int i;
try{
i=chatserver->UnregisterUser(username);
}
catch(CORBA::Exception &e)
{
cerr << e.get_id() << endl;
i=-2;
}
return i;
}
int corba_client::sendMessage(const char* sender,const char* receiver,const char* content)
{
if((Chat::ChatServer_ptr)chatserver == NULL)
return -1;
int i;
try{
Chat::Message msg;
msg.sender = CORBA::string_dup(sender);
msg.receiver = CORBA::string_dup(receiver);
msg.content = CORBA::string_dup(content);
i = chatserver->sendMessage(msg);
}
catch(CORBA::Exception &e)
{
cerr << e.get_id() << endl;
i=-2;
}
return i;
}
本软件的开发环境使用了Visual C++、VIsiBroker版本的CORBA中间件产品和Tuxedo 8.1。
软件除了具备发送消息、接收消息等基础的功能外,还实现了查看在线用户、群发消息、收发中文消息等许多功能,并解决了头疼的中文消息互发问题。