Ростислав А. Глухов ross2204@mail.ru
В этой статье рассмотрены некоторые вопросы,
встречающиеся при реализации распределенных систем,
построенных на технологии CORBA.
Примеры ориентированы на OmniORB 3.0.
Рассмотрим часто используемый порядок работы клиента и сервера. На рисунке ниже объект Client находится на Клиенте, объекты MyFactory и Connection - на Сервере.
|
Представленная схема позволяет:
POA (Portable Object Adapter) создает объекты c характеристиками, которые были заданы на стадии создания самого POA (или "временные" (transient), или "долгоживущие" (persistent)).
Во "временной" (transient) ссылке (IOR) присутствует информация о:
т.е., при следующем использовании такой ссылки, если сервер перезепущен и объект заново создан, этот объект клиентом не будет найден (во всяком случае, так должно быть).
"Долгоживущие" (persistent) ссылки не содержат "случайной информации", поэтому могут быть использованы после перезапуска сервера. "Долгоживущие" ссылки создаются при помощи POA с PortableServer::PERSISTENT lifespan_policy[1].
В нашем случае объект MyFactory должен иметь постоянную ссылку, Connection - временную.
Существует несколько способов получения IOR объекта.
Например
// Создаем и активизируем объект
MyFactory_impl* myFactory = new MyFactory_impl(); PortableServer::ObjectId_var myFactoryid = pers_poa->activate_object(myFactory); myFactory->_remove_ref(); // Получаем stringified IOR объекта CORBA::Object_var obj = myFactory->_this(); CORBA::String_varsior(orb->object_to_string(obj)); // Выводим stringified IOR в файл ofstream ior_file("ior_file.txt"); ior_file << "'" << (char*)sior << "'" << endl; PortableServer::POAManager_var pman = pers_poa->the_POAManager(); pman->activate(); |
публикует полученный полученный файл в доступном для клиента месте,
клиент читает SIOR и с помощью функции string_to_object() преобразует в ссылку на объект.
Например
// Читаем ссылку из файла
ifstream ior_file("ior_file.txt"); char buf[200]; ior_file >> buf; // Активизируем ссылку CORBA::Object_var obj = orb->string_to_object(buf); MyFactory_var MyFactoryref = MyFactoryEcho::_narrow(obj); |
Например, один из методов настройки resolve_initial_references для получения ссылки на NameService [2,разд.4.2.1] - поместить в файл C:\omniORB.cfg: NAMESERVICE IOR:далее_sior_полученный_методом_1
Например, Naming service [2,разд.2.10],[3],[4] или Trading service. Для получения ссылки на необходимое хранилище придется воспользоваться методом 1 или 2.
Например
// у сервера в параметрах командной строки должны присутствовать: -ORBpoa_iiop_port 1234 // где 1234 - номер порта, на котором сервер будет принимать запросы orb = CORBA::ORB_init(argc, argv, "omniORB3"); // ins_poa - для того, чтоб клиент смог подконнектиться к серверу по имени(IP) и порту CORBA::Object_var obj = orb->resolve_initial_references("omniINSPOA"); PortableServer::POA_var ins_poa = PortableServer::POA::_narrow(obj); PortableServer::POAManager_var ins_pman = ins_poa->the_POAManager(); ins_pman->activate(); // Always use the same object id. PortableServer::ObjectId_var oid = PortableServer::string_to_ObjectId("myPersistentFactory"); // Activate the Creator object... CmyFactory_impl* myFactory = new CmyFactory_impl(); ins_poa->activate_object_with_id(oid,myConn_Creator); myFactory->_remove_ref(); |
Со стороны клиента необходимо указать имя сервера и порт. ID объекта известен заранее.
Например : функция возвращает ссылку на объект
CORBA::Object_ptr getObjectReference2(CORBA::ORB_ptr orb, char *hostname, int port) { try { char cstr[8]; char sstr[1000]; strcpy(sstr, "corbaloc::"); strcat(sstr, hostname); strcat(sstr, ":"); if(!port) port = 3000; strcat(sstr, itoa(port,cstr,10)); strcat(sstr, "/myPersistentFactory"); // sstr: "corbaloc::host_name:port_number/myPersistentFactory" // меняются: host_name,port_number returnorb->string_to_object(sstr); }catch(CORBA::COMM_FAILURE& ex){ cerr << "Caught system exception COMM_FAILURE -- unable to contact the remote server." << endl; } catch(CORBA::SystemException & ) { cerr << "Caught a CORBA::SystemException while contacting remote server." << endl; } return CORBA::Object::_nil(); } |
Если и клиент и сервер работают на одном компьютере, то в качестве имени сервера можно использовать "localhost".
Под сборкой мусора будем понимать удаление сервантов из памяти процесса сервера после окончания необходимости в соответствующих (transient) объектах.
Отдельным тредом запускается контроллер Call-Back объекта. Если Call-Back объект не отвечает, удаляем сервант серверного объекта.
Если использовать CallBack-объекты, то при работе через интернет клиент, спрятанный за прокси, виден не будет, т.к в ссылку на CallBack попадает IP адрес локальной сети. При работе внутри локальной сети этот механизм вполне работоспособен.
Например
void Connection_impl::Deactivate() { PortableServer::POA_var poa = _default_POA(); // если объект использует именно _default_POA() PortableServer::ObjectId_var oid = poa->servant_to_id(this); poa->deactivate_object(oid); // Если объект не отнаследован от PortableServer::RefCountServantBase, то раскомментировать след. строку // delete this; } |
При разрыве коннекта (смерти клиента) этот метод никогда не будет вызван и объект останется висеть в памяти сервера на веки вечные.
Суть метода состоит в в удалении сервером объектов, последнее обращение к которым произошло давно.