opendds初入门之对inforepo模式运行探索

opendds的集中模式inforepo一般是在主线程中运行,直接run进行阻塞等待,内部有一系列的资源初始化以及ace和tao的相关底层资源。

业务探索,需要把inforepo的集中模式和UI界面进行配合使用,也就是说ui是主进程,而inforepo需要移到子线程中处理。

补充:opendds下的项目,每个项目下都自带一个可执行脚本run_test.pl,对于测试样例,可以在对应项目生成可执行文件目录下执行perl run_test.pl进行运行演示,观察现象。

复制代码
C:\Users\LEGION\Desktop\opendds_study\OpenDDS\DevGuideExamples\DCPS\Messenger>perl run_test.pl
C:\Users\LEGION\Desktop\opendds_study\OpenDDS\bin\.\DCPSInfoRepo.EXE -ORBDebugLevel 1 -ORBLogFile DCPSInfoRepo.log -o repo.ior -DCPSPendingTimeout 3
InfoRepo PID: 24272
.\.\subscriber.EXE  -ORBDebugLevel 1 -DCPSDebugLevel 4 -ORBVerboseLogging 1 -DCPSTransportDebugLevel 2 -ORBLogFile subscriber.log -DCPSPendingTimeout 3
subscriber PID: 25360 started at 2025-07-09 17:36:59
.\.\publisher.EXE  -ORBDebugLevel 1 -DCPSDebugLevel 4 -ORBVerboseLogging 1 -DCPSTransportDebugLevel 2 -ORBLogFile publisher.log -DCPSPendingTimeout 3

说明:本次是在理解不完善的角度上考虑实现方案的探索。

1:首先了解一下inforepo的作用,主观理解,还未验证。

这里并不是以tcp的交互方式,而是基于tcp的corba,待实际确定!

2:基于现有主进程的方式,首先进行测试一下相关集中模式的发布订阅。

bash 复制代码
#基于源代码编译后的产物,内部有demo 可以查看验证结果
#执行 perl run_test.pl  可以直接运行,也可以看到内部自带调用指令。
C:\Users\LEGION\Desktop\opendds_study\OpenDDS\bin\.\DCPSInfoRepo.EXE -ORBDebugLevel 1 -ORBLogFile DCPSInfoRepo.log -o repo.ior -DCPSPendingTimeout 3

同时,这个脚本,也是一个很好的命令指令样本。

bash 复制代码
C:\Users\LEGION\Desktop\opendds_study\OpenDDS\bin\.\DCPSInfoRepo.EXE -ORBDebugLevel 1 -ORBLogFile DCPSInfoRepo.log -o repo.ior -DCPSPendingTimeout 3
.\.\subscriber.EXE  -ORBDebugLevel 1 -DCPSDebugLevel 4 -ORBVerboseLogging 1 -DCPSTransportDebugLevel 2 -ORBLogFile subscriber.log -DCPSPendingTimeout 3
.\.\publisher.EXE  -ORBDebugLevel 1 -DCPSDebugLevel 4 -ORBVerboseLogging 1 -DCPSTransportDebugLevel 2 -ORBLogFile publisher.log -DCPSPendingTimeout 3

可以写入日志进行查看日志,确定一些必要信息。

bash 复制代码
C:\Users\LEGION\Desktop\opendds_study\OpenDDS\bin\.\DCPSInfoRepo.EXE  -ORBListenEndpoints iiop://127.0.0.1:12345

subscriber.EXE -DCPSInfoRepo iiop://127.0.0.1:12345 -ORBDebugLevel 1 -DCPSDebugLevel 4 -ORBVerboseLogging 1 -DCPSTransportDebugLevel 2 -ORBLogFile subscriber.log -DCPSPendingTimeout 3
publisher.EXE  -DCPSInfoRepo iiop://127.0.0.1:12345 -ORBDebugLevel 1 -DCPSDebugLevel 4 -ORBVerboseLogging 1 -DCPSTransportDebugLevel 2 -ORBLogFile publisher.log -DCPSPendingTimeout 3

最后,依赖操作系统自动分配节点的时候,可能发现和中心节点网络交互问题,主机可能多个ip吧。

所以,手动指定客户端ip进行跨主机测试。

bash 复制代码
#在pub和sub运行时加参数  
-DCPSDefaultAddress 192.168.1.161:3333

看到一个差异,集中节点的配置如下两种,有什么区别?

-DCPSInfoRepo corbaloc::192.168.1.161:12345/DCPSInfoRepo 和-DCPSInfoRepo iiop://127.0.0.1:12345有什么区别

复制代码
corbaloc::192.168.1.161:12345/DCPSInfoRepo    是CORBA对象的"定位名称",明确指定了对象名称,连接可靠,生产环境推荐。
iiop://127.0.0.1:12345                        CORBA的iiop:地址(这是ACE/TAO特定的URL格式),仅指定了IIOP协议下的主机和端口,但没有指定对象名称缺少对象名,依赖默认绑定,可能失败或不确定。 推荐本地测试用。

3:考虑在子线程中运行测试。

核心目的是期望Inforepo的线程和主线程UI界面共存。

这里首先测试在子线程中要启动运行正常。

c 复制代码
//这里注意,InfoRepo的启动依赖主线程还是底层的一些资源,最终是ACE_OS::thr_self();和CORBA::ORB_init(argc, argv);加上后处理正常。
//这里注意,函数内定义的线程的局部变量,在不加detach()或者join时,线程出作用域释放,会导致崩溃问题。
#include "DCPSInfoRepoServ.h"

#ifdef ACE_AS_STATIC_LIBS
#  include <dds/DCPS/InfoRepoDiscovery/InfoRepoDiscovery.h>
#endif

#include <iostream>
#include <thread>
int
ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
	std::vector<std::string> args = {
		"InfoRepoService",
		"-ORBListenEndpoints", "iiop://192.168.1.161:12345"
	};

	try {

		std::thread t([args]() {
			
			ACE_OS::thr_self();
			std::vector<char*> argv_vec;
			for (auto& s : args)
				argv_vec.push_back(const_cast<char*>(s.c_str()));

			int argc = argv_vec.size();
			char** argv = argv_vec.data();

			CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

			if (!CORBA::is_nil(orb)) {
				std::cout << "[INFO] ORB_init() 成功" << std::endl;
			}
			else {
				std::cerr << "[ERROR] ORB_init() 返回空对象(CORBA::is_nil)" << std::endl;
			}

			// 你也可以测试 resolve_initial_references 是否能继续工作
			CORBA::Object_var poa_obj = orb->resolve_initial_references("RootPOA");
			if (!CORBA::is_nil(poa_obj)) {
				std::cout << "[INFO] RootPOA resolved 成功" << std::endl;
			}
			else {
				std::cerr << "[ERROR] 无法 resolve RootPOA" << std::endl;
			}

			InfoRepo infoRepo(argc, argv);

            //这里是为了接受终端上的一些退出信号做处理吗?
			InfoRepo_Shutdown ir_shutdown(infoRepo);
			Service_Shutdown service_shutdown(ir_shutdown);

			std::cout << "infoRepo has run start.";
			infoRepo.run();
			std::cout << "infoRepo has run end.";
            orb->destroy();
		});
		t.join();
	}
	catch (InfoRepo::InitError& ex) {
		std::cerr << "Unexpected initialization Error: "
			<< ex.msg_ << std::endl;
		return 1;

	}
	catch (const CORBA::Exception& ex) {
		ex._tao_print_exception("ERROR: DDS DCPS Info Repo caught exception");
		return 1;
	}

  return 0;
}

4:考虑停止的逻辑。

基于UI界面的操作,类似上面的逻辑可以通过控件控制启动。

本来设想的是,基于Inforepo的特性,他需要持久化运行,不应该被停止,因为停止后丢失了先前的发布订阅信息。

但是,领导要求停止,所以考虑一下停止的方案。

所以本身让inforepo停止是不合理的,如果要停止,需要做持久化或者其他方案支持。

但是基于技术的角度,尝试使用停止的测试方案。

可探索,基于inforepo集中模式ior,可以考虑配合imr,iogr,以及inforepo联邦进行业务部署。

相关推荐
jason成都2 个月前
ubuntu编译opendds开发(C#)
linux·ubuntu·c#·opendds
林夕072 年前
OpenDDS之QosXml库编译(Windows + VS2019)
编译·dds·opendds