В этой статье рассмотрены некоторые вопросы, встречающиеся при реализации распределенных систем, построенных на технологии CORBA. Примеры ориентированы на OmniORB 3.0.
Рассмотрим часто используемый порядок работы клиента и сервера. На рисунке ниже объект Client находится на Клиенте, объекты MyFactory и Connection - на Сервере.
Sample Sequence Diagram
Представленная схема позволяет:
POA (Portable Object Adapter) создает объекты c характеристиками, которые были заданы на стадии создания самого POA (или "временные" (transient), или "долгоживущие" (persistent)).
Во "временной" (transient) ссылке (IOR) присутствует информация о:
т.е., при следующем использовании такой ссылки, если сервер перезепущен и объект заново создан, этот объект клиентом не будет найден (во всяком случае, так должно быть).
"Долгоживущие" (persistent) ссылки не содержат "случайной информации", поэтому могут быть использованы после перезапуска сервера. "Долгоживущие" ссылки создаются при помощи POA с PortableServer::PERSISTENT lifespan_policy [1].
В нашем случае объект MyFactory должен иметь постоянную ссылку, Connection - временную.
Существует несколько способов получения IOR объекта.
При запуске сервер преобразует IOR объекта в строку с помощью функции object_to_string(), например:
// Создаем и активизируем объект 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); |
Эта функция предоставляет клиенту набор ссылок на несколько предопределенных служб (Naming, Trading, Interface Repository и т.п.). Эти службы можно использовать для получения необходимых ссылок.
Возвращаемые значения resolve_initial_references необходимо настраивать на каждой клиентской машины. (Для каждого ORB по-разному) [2,разд.4.2].
Например, один из методов настройки 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.
INS (Interoperable Name Service) POA [2,разд.4.5],[5] позволяет создавать объекты с унифицированными идентификаторами ресурсов (Uniform Resource Identifierkeys - URI) вида "corbaloc::hostname:port/Object_key".
Это можно сделать (в omniORB) при помощи специального POA "omniINSPOA", полученного посредством resolve_initial_references(). Этот POA позволяет создавать объекты ссылки которых содержат только переданный POA при создании ID объекта.
Например:
// у сервера в параметрах командной строки должны присутствовать: -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; } |
При разрыве коннекта (смерти клиента) этот метод никогда не будет вызван и объект останется висеть в памяти сервера на веки вечные.
Суть метода состоит в в удалении сервером объектов, последнее обращение к которым произошло давно.