上一篇文章中我们主要介绍了vsomeip库如何编译,以及成功的运行了helloworld的程序。
这一篇主要分析helloworld程序的服务端的运行。
相关代码目录:
examples/hello_world/hello_world_service_main.cpp
examples/hello_world/hello_world_service.hpp
首先从main函数开始分析,这里helloworld主要调用了hello_world_service类去做初始化和启动的过程。
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
hello_world_service hw_srv;
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
hw_srv_ptr = &hw_srv;
signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal);
#endif
if (hw_srv.init()) {
hw_srv.start();
return 0;
} else {
return 1;
}
}
关于信号相关的机制,本次暂时不做分析。我们先看非信号情况下的流程。
// Get the vSomeIP runtime and
// create a application via the runtime, we could pass the application name
// here otherwise the name supplied via the VSOMEIP_APPLICATION_NAME
// environment variable is used
//这里的create_application(const std::string &_name)可以指定对应的name的
hello_world_service() :
rtm_(vsomeip::runtime::get()),
app_(rtm_->create_application()),
stop_(false),
stop_thread_(std::bind(&hello_world_service::stop, this))
{
}
默认构造函数中,创建对应someip的runtime对象,application对象。
这里构造函数中,create_application的时候,是可以指定对应的application name的,这里在官方的代码中,相关application name的指定是在我们启动helloworld程序的时候使用环境变量的方式指定的。
我理解这里后续工程化实现的时候,肯定是需要再代码里面指定。
main函数中调用了对应的init进行初始化。这里调用到了hello_world_service这个class,并且实际服务的实现也是再这个类里面。
bool init()
{
// init the application
if (!app_->init()) {
LOG_ERR("Couldn't initialize application");
return false;
}
//注册一个message handler,用于处理client访问时收到的请求,这里注册了on_message_cbk函数
// register a message handler callback for messages sent to our service
app_->register_message_handler(service_id, service_instance_id,
service_method_id,
std::bind(&hello_world_service::on_message_cbk, this,
std::placeholders::_1));
// register a state handler to get called back after registration at the
// runtime was successful
//只有对应的服务状态正常后,才会提供对应的服务。
//因此这里监听一下状态
app_->register_state_handler(
std::bind(&hello_world_service::on_state_cbk, this,
std::placeholders::_1));
return true;
}
初始化的函数中,首先是对我们之前创建的application对象进行初始化,app_->init()这个函数主要做了如下几件事情:
基本application对象初始化完毕,这里注册了两个回调函数,一个是on_message_cbk主要用来处理收到client的request后的事情。
还有一个函数 on_state_cbk,主要处理,相关的服务再routing中注册成功后的操作。
初始化完毕后,相关的回调函数也已经注册,这时候,就可以调用start函数进行启动了。
void start()
{
// start the application and wait for the on_event callback to be called
// this method only returns when app_->stop() is called
app_->start();
}
hello_wrold_service的start函数比较简单,直接调用了application的start函数。
这里app_->start()回去启动对应的线程。
主要有如下的几种:
主线程(hello_world_service)
io线程(4444_io01)
maindispatch线程(4444_m_dispatch)
stop_thread线程(4444_shutdown)
Routing线程(4444_client_reg)
可以看到hello_world_service启动后,对应的线程信息。
Start()内部还会处理连接routing的操作,并建立相关与routing通信的socket,建立完成之后,会设置对应的state_type_e::ST_REGISTERED状态,并调用之前注册的回调函数on_state_cbk,执行后续操作。
这里routing线程实际上不是所有的进程都会创建的,由于在helloworld的启动配置文件中,我们指定了对应的routing进程就是hello_world_service,所以这里才会去创建对应的routing.
void on_state_cbk(vsomeip::state_type_e _state)
{
if(_state == vsomeip::state_type_e::ST_REGISTERED)
{
// we are registered at the runtime and can offer our service
// 对应提供服务
app_->offer_service(service_id, service_instance_id);
}
}
Offer_service操作首先会在本地进程的内存信息中查找,当前服务是否已经注册发布,如果没有,会创建对应的service info。并且当前的state是ST_REGISTERED的话,那么就会发送对应的发布服务请求给routing进程。
同时这里如果服务offer是成功的,也会去通知对应的client,来调用其on_avaliability_cbk回调函数
void on_message_cbk(const std::shared_ptr &_request)
{
// Create a response based upon the request
std::shared_ptr resp = rtm_->create_response(_request);
// Construct string to send back
std::string str("Hello ");
str.append(reinterpret_cast(_request->get_payload()->get_data()),
0, _request->get_payload()->get_length());
// Create a payload which will be sent back to the client
std::shared_ptr resp_pl = rtm_->create_payload();
std::vector pl_data(str.begin(), str.end());
res p_pl->set_data(pl_data);
resp->set_payload(resp_pl);
// Send the response back
app_->send(resp);
// we have finished
terminate();
}
Helloworld程序的接收消息相关的操作比较简单,主要就是在on_message_cbk中执行的.
在on_message_cbk中,可以看到入参的是完整的message信息.这里应该可以拿到完整的someip包的信息.相关的message信息我们后续再详细分析.
在on_message_cbk中其实做的事情很简单,就是接收到client发来的world字符串,然后和hello进行组合,形成helloworld,然后返回给client.
void stop()
{
std::unique_lock its_lock(mutex_);
while(!stop_) {
condition_.wait(its_lock);
}
std::this_thread::sleep_for(std::chrono::seconds(5));
// Stop offering the service
app_->stop_offer_service(service_id, service_instance_id);
// unregister the state handler
app_->unregister_state_handler();
// unregister the message handler
app_->unregister_message_handler(service_id, service_instance_id,
service_method_id);
// shutdown the applicationg
app_->stop();
}
Helloworld的stop函数主要是在client的消息调用完之后处理了,正常我们开发这里肯定需要继续服务的,因此在工程化实现的过程当中,肯定不能在on_message中去结束服务.
这里结束函数主要就是针对的就是我们初始化阶段的那些操作,首先是stop_offer_service,然后unregister我们初始化注册的message_handler和state_handler.
最后执行app_->stop.