<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    vsomeip: SOME/IP 開源實現

    VSole2022-06-06 12:26:14

    vsomeip 是 GENIVI 實現的開源 SOME/IP 庫,由 C++ 編寫,目前主要實現了 SOME/IP 的通信和服務發現功能,并在此基礎上增加了少許的安全機制。

    GENIVI是一個聯盟組織,由 BMW 倡導,是汽車信息娛樂領域系統軟件標準的倡導者,創建基于linux 系統的 IVI 軟件平臺和操作系統。GENIVI 倡導了很多開源軟件項目,比如:DLT、CommonAPI C++、vSOMEIP。

    vsomeip 概述

    簡單了解一下 vsomeip的基本結構。

    如圖所示,vsomeip 不僅涵蓋了設備之間的 SOME/IP 通信(外部通信),還涵蓋了內部進程間通信。兩個設備通過communication endpoints(通信端點)進行通信,endpoints 確定傳輸使用的協議(TCP 或 UDP)及端口號或其他參數。所有這些參數都是可以在 vsomeip 配置文件中設置的(配置文件是 json 格式)。內部通信是通過本地 endpoints 完成的,這些 endpoints 由 unix 域套接字使用 Boost.Asio 庫實現。由于這種內部通信不是通過中心組件 (例如 D-Bus 守護進程) 路由的,所以它非常快。

    中央 vsomeip 路由管理器(routing manager)只接收必須發送到外部設備的消息,并分發來自外部的消息。每個設備只有一個路由管理器,如果沒有配置,那么第一個運行的 vsomeip 應用程序也會啟動路由管理器。

    vsomeip 部署安裝

    以下操作在 Ubuntu 16.04 虛擬機上進行。

    vsomeip 需要:

    1、一個支持c++ 11的編譯器,比如 gcc >= 4.8。

    2、使用 CMake 作為構建系統。

    3、Boost >= 1.55。

    sudo apt-get install libboost-system1.55-dev libboost-thread1.55-dev libboost-log1.55-dev

    編譯 vsomeip 前先還需要安裝一些其他依賴,像是要構建文檔需要的 asciidoc,source-highlight、doxygen 和 graphviz:

    sudo apt-get install source-highlight doxygen graphviz

    sudo apt-get --no-install-recommends install asciidoc

    編譯:

    git clone https://github.com/COVESA/vsomeip.git

    cd vsomeip

    <.>/vsomeip$ mkdir build

    <.>/vsomeip$ cd build

    <.>/vsomeip/build$ cmake -DENABLE_SIGNAL_HANDLING=1 ..

    <.>/vsomeip/build$ make

    <.>/vsomeip/build$ make install

    cmake 命令中添加的參數 -DENABLE_SIGNAL_HANDLING=1 可以確保終止 vsomeip 應用程序的時候不出問題,否則當使用 Ctrl-c 停止應用時,共享內存段 /dev/shm/vsomeip 可能未被正確刪除。

    經過以上操作就編譯出 vsomeip 庫了。

    入門示例演示

    創建第一個 vsomeip 應用 service-example,它的唯一功能就是初始化并啟動一個名叫 “World”的應用。

    首先創建一個service-example.cpp,代碼如下:

    #include 

    std::shared_ptr< vsomeip::application > app;

    int main() {

       app = vsomeip::runtime::get()->create_application("World");

       app->init();

       app->start();

    }

    上面代碼中,首先創建了一個application 對象,然后調用 init() 和start() 分別進行初始化和啟動。需要注意,在創建 application 后,必須首先調用 init 方法,初始化時會執行以下幾步:

    • 加載配置。
    • 確定路由配置和路由的初始化。
    • 安裝信號處理程序。

    為了啟動消息處理,必須在 init 之后調用 start 方法。接收到的消息通過套接字進行處理,并使用已注冊的回調函數將它們傳遞給用戶 application。

    接下來創建一個 CMakeLists.txt文件來構建 service-example 應用。

    cmake_minimum_required (VERSION 2.8)

    set (CMAKE_CXX_FLAGS "-g -std=c++0x")

    find_package (vsomeip 2.6.0 REQUIRED)

    find_package( Boost 1.55 COMPONENTS system thread log REQUIRED )

    include_directories (

       ${Boost_INCLUDE_DIR}

       ${VSOMEIP_INCLUDE_DIRS}

    )

    add_executable(service-example ../src/service-example.cpp)

    target_link_libraries(service-example vsomeip ${Boost_LIBRARIES})

    上述 CMakeLists.txt 文件中部分項解釋如下:

    cmake_minimum_required  # 指定 cmake 的最小版本

    CMAKE_CXX_FLAGS # 設置編譯選項 ,如果編譯器支持 -std=c++11,則沒有理由使用 -std=c++0x。

    find_package # 查找到指定的預編譯庫,并將它的路徑存儲在變量中。默認的搜索路徑為 cmake 包含的系統庫,因此如果是 NDK 的公共庫只需要指定庫的 name 即可

    include_directories # 設置包含的目錄

    add_executable # 生成可執行文件

    target_link_libraries  # 設置 target 需要鏈接的庫

    service-example.cpp 和 CMakeLists.txt 寫好之后,在同目錄下創建一個build 文件夾,在 build 文件夾中運行 cmake -DENABLE_SIGNAL_HANDLING=1 .. ,再執行 make。

    不過直接使用項目中的CMakeLists.txt 時會報錯,最終修改如下:

    cmake_minimum_required (VERSION 2.8.7)

    project (vSomeIPServiceExample)

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

    find_package(Threads REQUIRED)

    include_directories("/home/ml/car/vsomeip")

    link_directories("/usr/local/lib")

    include_directories(${VSOMEIP_INCLUDE_DIRS})

    include_directories(${Boost_INCLUDE_DIR})

    find_package(vsomeip3 REQUIRED)

    add_executable(service-example ../service-example.cpp)

    target_link_libraries(service-example vsomeip3 pthread)

    #add_executable (client-example ../client-example.cpp)

    #target_link_libraries(client-example vsomeip ${Boost_LIBRARIES})

    運行之后會打印如下內容:

    這些步驟對于服務和客戶端是相同的,沒有區別。到目前為止,不需要任何配置文件。

    再來看看輸出中的一些細節:

    • 首先顯示已經加載的配置,不過由于我們沒有配置,所以這里會使用默認值。
    • 由于路由管理器(routing manager)也沒有配置,因此,路由管理器會在系統中的第一個vsomeip應用程序 (即 service-example) 啟動時自動啟動。
    • 默認情況下,Service Discovery 會啟用,不過沒有靜態路由,這需要一些配置參數。
    • Application(World, 0100) is initialized (11,100)。最后的兩個數字表示如果回調阻塞超過100毫秒,則 vsomeip 使用的最大調度程序數量為 11。這些參數可以配置。
    • 默認情況下,會創建了兩個線程來接收SOME/IP消息,這使得 vsomeip 可以并行處理長消息。

    假設 service-example 在服務端并且需要編寫一個使用該服務的客戶端。第一步,必須觸發應用程序提供服務實例,可以通過在之前的示例中添加一個offer_service函數來完成。

    #include 

    #define SAMPLE_SERVICE_ID 0x1234

    #define SAMPLE_INSTANCE_ID 0x5678

    std::shared_ptr< vsomeip::application > app;

    int main() {

       app = vsomeip::runtime::get()->create_application("World");

       app->init();

       app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);

       app->start();

    }

    接下來,編寫一個客戶端應用程序來檢測正在運行的“World“應用程序是否可用,這里創建一個名為 client-example.cpp 的文件:

    #include

    #include

    #include 

    #define SAMPLE_SERVICE_ID 0x1234

    #define SAMPLE_INSTANCE_ID 0x5678

    std::shared_ptr< vsomeip::application > app;

    void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {

       std::cout << "Service ["

               << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance

               << "] is " << (_is_available ? "available." : "NOT available.") << std::endl;

    }

    int main() {

       app = vsomeip::runtime::get()->create_application("Hello");

       app->init();

       app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);

       app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);

       app->start();

    }

    在 CMakeLists.txt 中添加兩句:

    add_executable (client-example ../client-example.cpp)

    target_link_libraries(client-example vsomeip3 pthread)

    編譯后只執行 client-example,打印第一個紅框,在另一個終端中啟動 service-example 之后,打印中出現第二個紅框:

    為了使其盡可能簡單,代碼中省略了所有可能的檢查,例如沒有檢查注冊是否成功。作為客戶端,要想告訴 vsomeip 自己想使用這個服務,客戶端就需要注冊一個回調函數以便在服務可用時獲得一個回調,在本例中,回調函數就是 on_availability。

    Request/Response 示例

    上面的 vsomeip 應用程序中,我們創建了一個提供服務接口實例的服務端程序和一個想要使用這個接口的客戶端程序。

    下一步將在服務端實現一個可由客戶端調用的函數。為此服務端必須為接收消息做好準備,可以通過注冊消息處理程序(register_message_handler)來實現。編寫代碼如下:

    service-example.cpp

    #include

    #include

    #include

    #include 

    #define SAMPLE_SERVICE_ID 0x1234

    #define SAMPLE_INSTANCE_ID 0x5678

    #define SAMPLE_METHOD_ID 0x0421

    std::shared_ptr app;

    void on_message(const std::shared_ptr &_request) {

       std::shared_ptr its_payload = _request->get_payload();

       vsomeip::length_t l = its_payload->get_length();

       // Get payload

       std::stringstream ss;

       for (vsomeip::length_t i=0; i

          ss << std::setw(2) << std::setfill('0') << std::hex

             << (int)*(its_payload->get_data()+i) << " ";

       }

       std::cout << "SERVICE: Received message with Client/Session ["

           << std::setw(4) << std::setfill('0') << std::hex << _request->get_client() << "/"

           << std::setw(4) << std::setfill('0') << std::hex << _request->get_session() << "] "

           << ss.str() << std::endl;

       // Create response

       std::shared_ptr its_response = vsomeip::runtime::get()->create_response(_request);

       its_payload = vsomeip::runtime::get()->create_payload();

       std::vector its_payload_data;

       for (int i=9; i>=0; i--) {

           its_payload_data.push_back(i % 256);

       }

       its_payload->set_data(its_payload_data);

        its_response->set_payload(its_payload);

       app->send(its_response);

    }

    int main() {

      app = vsomeip::runtime::get()->create_application("World");

      app->init();

      app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);

      app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);

      app->start();

    }

    服務端提供 message_handler 和offer 功能。

    register_message_handler函數在 \vsomeip-master\interface\vsomeip\application.hpp 中的定義描述為:

    virtual void register_message_handler(service_t _service,

               instance_t _instance, method_t _method,

                message_handler_t _handler) = 0;    

    為指定的 method 或 event 注冊處理程序。用戶應用程序必須調用此方法來為其注冊回調。

    注:

    每個服務(SERVICE)、實例(INSTANCE)、方法/事件(METHOD)組合只能注冊一個處理程序。

    offer_service函數在 \vsomeip-master\interface\vsomeip\application.hpp 中的定義描述為:

    virtual void offer_service(service_t _service, instance_t _instance,

               major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =

                       DEFAULT_MINOR) = 0;

    參數 _service:service標識符;

    參數 _instance:提供的服務實例的實例標識符;

    參數 _major:主服務版本號(默認為0);

    參數 _minor:次服務版本號(默認為0)。

    offer_service 函數的作用是將service 注冊到 vsomeip 路由組件上,從而使感興趣的客戶端可以看到該服務,因此用戶應用程序必須為它提供的每個 service 調用offer_service這個方法。根據配置,service有兩種模式,一種是只能在內部網絡中可用的,另一種是在內部和外部均可使用。為了向外部網絡提供服務,配置中必須包含提供服務實例的端口,如果沒有提供這樣的端口配置,服務在設備外部是不可見的。

    再來看客戶端,request-example.cpp中包含 message handler 和 send 功能,代碼如下:

    #include

    #include

    #include

    #include 

    #include

    #include 

    #define SAMPLE_SERVICE_ID 0x1234

    #define SAMPLE_INSTANCE_ID 0x5678

    #define SAMPLE_METHOD_ID 0x0421

    std::shared_ptr< vsomeip::application > app;

    std::mutex mutex;

    std::condition_variable condition;

    void run() {

     std::unique_lock its_lock(mutex);

     condition.wait(its_lock);

     std::shared_ptr< vsomeip::message > request;

     request = vsomeip::runtime::get()->create_request();

     request->set_service(SAMPLE_SERVICE_ID);

      request->set_instance(SAMPLE_INSTANCE_ID);

     request->set_method(SAMPLE_METHOD_ID);

     std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();

     std::vector< vsomeip::byte_t > its_payload_data;

     for (vsomeip::byte_t i=0; i<10; i++) {

         its_payload_data.push_back(i % 256);

     }

     its_payload->set_data(its_payload_data);

     request->set_payload(its_payload);

     app->send(request);

    }

    void on_message(const std::shared_ptr &_response) {

     std::shared_ptr its_payload = _response->get_payload();

     vsomeip::length_t l = its_payload->get_length();

     // Get payload

     std::stringstream ss;

     for (vsomeip::length_t i=0; i

        ss << std::setw(2) << std::setfill('0') << std::hex

           << (int)*(its_payload->get_data()+i) << " ";

     }

     std::cout << "CLIENT: Received message with Client/Session ["

         << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() << "/"

         << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "] "

         << ss.str() << std::endl;

    }

    void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {

       std::cout << "CLIENT: Service ["

               << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance

               << "] is "

               << (_is_available ? "available." : "NOT available.")

               << std::endl;

       condition.notify_one();

    }

    int main() {

       app = vsomeip::runtime::get()->create_application("Hello");

       app->init();

       app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);

       app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);

       app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);

       std::thread sender(run);

       app->start();

    }

    與服務端的代碼一樣,在客戶端代碼中我們也需要調用 register_message_handler 注冊一個消息處理程序,用來接收服務器對客戶端請求的響應。原則上,創建請求消息非常容易。只需通過調用 create_request() 獲取請求對象,設置 service ID、instance ID 和 method ID,并在最后將序列化的數據寫入payload。在上面這個示例中,我們將 0 到 9 的值寫入有效負載(std::vector< vsomeip::byte_t >)。

    上述代碼中出現 “std::thread sender(run);” 的原因是:當我們嘗試將請求從客戶端發送給服務時,遇到了一個小問題。在發送消息之前必須啟動應用程序(app->start()),因為我們需要一個正在運行的事件循環來處理消息。但是該方法 app->start() 不會返回,因為它內部有正在運行的事件循環。因此,就需要啟動一個線程(run),并在此線程中等待 availability 回調的返回,然后再調用app->send(request)。

    上述兩個cpp文件還有 CMakeLists.txt 寫好之后,在同目錄下創建一個 build 文件夾,在 build 文件夾中運行 cmake -DENABLE_SIGNAL_HANDLING=1 .. ,再執行 make。

    先執行 service-example 再執行 request-example 之后,結果如下:

    Subscribe/Notify 示例

    在以下 Subscribe/Notify(訂閱/通知)示例中,

    先來看服務端代碼:

    #include

    #include

    #include

    #include 

    #define SAMPLE_EVENTGROUP_ID 0x3333

    #define SAMPLE_SERVICE_ID 0x1234

    #define SAMPLE_INSTANCE_ID 0x5678

    #define SAMPLE_EVENT_ID 0x4444

    std::shared_ptr app;

    int main() {

      app = vsomeip::runtime::get()->create_application("World");

      app->init();

      app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);

      const vsomeip::byte_t its_data[] = { 0x22 };

      std::shared_ptr payload = vsomeip::runtime::get()->create_payload();

      payload->set_data(its_data, sizeof(its_data));

      std::set its_groups;

      its_groups.insert(SAMPLE_EVENTGROUP_ID);

      app->offer_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_groups);

      app->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload);

      app->start();

    }

    注意在 offer_event 之前offer_service 不可或缺。

    客戶端代碼如下:

    #include

    #include

    #include

    #include 

    #include

    #include 

    #define SAMPLE_EVENTGROUP_ID 0x3333

    #define SAMPLE_SERVICE_ID 0x1234

    #define SAMPLE_INSTANCE_ID 0x5678

    #define SAMPLE_EVENT_ID 0x4444

    std::shared_ptr< vsomeip::application > app;

    std::mutex mutex;

    std::condition_variable condition;

    void run() {

     std::unique_lock its_lock(mutex);

     condition.wait(its_lock);

     std::set its_groups;

     its_groups.insert(SAMPLE_EVENTGROUP_ID);

     app->request_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_groups);

     app->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID);

    }

    void on_message(const std::shared_ptr &_response) {

       std::stringstream its_message;

       its_message << "CLIENT: received a notification for event ["

               << std::setw(4) << std::setfill('0') << std::hex

               << _response->get_service() << "."

               << std::setw(4) << std::setfill('0') << std::hex

               << _response->get_instance() << "."

               << std::setw(4) << std::setfill('0') << std::hex

               << _response->get_method() << "] to Client/Session ["

               << std::setw(4) << std::setfill('0') << std::hex

               << _response->get_client() << "/"

               << std::setw(4) << std::setfill('0') << std::hex

               << _response->get_session()

               << "] = ";

       std::shared_ptr its_payload = _response->get_payload();

       its_message << "(" << std::dec << its_payload->get_length() << ") ";

       for (uint32_t i = 0; i < its_payload->get_length(); ++i)

           its_message << std::hex << std::setw(2) << std::setfill('0')

               << (int) its_payload->get_data()[i] << " ";

       std::cout << its_message.str() << std::endl;

    }

    void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {

       std::cout << "CLIENT: Service ["

               << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance

               << "] is "

               << (_is_available ? "available." : "NOT available.")

               << std::endl;

       condition.notify_one();

    }

    int main() {

       app = vsomeip::runtime::get()->create_application("Hello");

       app->init();

       app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);

       app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);

       app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, on_message);

       std::thread sender(run);

       app->start();

    }

    兩個設備間的通信

    要實現兩個設備間的通信,無需修改 c++ 代碼,不過需要編寫配置文件。

    配置文件是由 json 格式編寫的,默認配置文件是/etc/vsomeip.json,默認配置文件夾是 /etc/vsomeip。不過如果可執行文件同目錄下存在 ./vsomeip.json或 ./vsomeip 文件夾時,則用本地的配置文件。如果環境變量 “VSOMEIP_CONFIGURATION” 設為有效的文件或目錄路徑,則會使用該環境變量中所指定的配置(此時既不會使用默認文件/文件夾,也不會使用本地文件/文件夾)。

    在下面的配置示例中,服務器和客戶端程序分別運行在兩臺 ubuntu 16.04 的虛擬機上,服務端所在虛擬機地址為192.168.24.132 的設備上,客戶端地址為 192.168.24.129。

    首先,看一下服務器端配置的示例。

    {

       "unicast" : "192.168.24.132",

       "logging" :

       {

           "level" : "debug",

           "console" : "true",

           "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },

           "dlt" : "false"

       },

       "applications" :

       [

           {

               "name" : "World",

               "id" : "0x1212"

           }

       ],

       "services" :

       [

           {

               "service" : "0x1234",

               "instance" : "0x5678",

               "unreliable" : "30509"

           }

       ],

       "routing" : "World",

       "service-discovery" :

       {

           "enable" : "true",

           "multicast" : "224.224.224.245",

           "port" : "30490",

           "protocol" : "udp",

           "initial_delay_min" : "10",

           "initial_delay_max" : "100",

           "repetitions_base_delay" : "200",

           "repetitions_max" : "3",

           "ttl" : "3",

           "cyclic_offer_delay" : "2000",

           "request_response_delay" : "1500"

       }

    }

    對其中的部分項進行說明:

    • 對于 IP 通信,單播(unicast )地址是必須的。
    • logging:這里面的設置是可選的,設置 "console"=true 可以查看控制臺上的日志消息。
    • applications:可以為每個 application (application 是通過 create_application() 創建的) 定義固定的ID,而不是由自動配置決定。這將有助于在后續跟蹤中有效識別出applications。applications 中 id 是必須設置的,因為這個值在網絡中必須是惟一的。如果不設置該 id,自動配置將把每個設備上的 id 都設置為 1,通信將無法工作。
    • services:對于每個服務實例(service instance),必須定義在哪個端口下可以訪問它。如果端口為“unreliable”,則說明是 UDP 端口,如果端口為“reliable”,則是 TCP 端口。
    • routing:每個設備只有一個路由管理器。這個路由管理器將被附加到第一個啟動的vsomeip 應用程序或該項定義的應用程序。
    • service-discovery:這里的所有參數只有在啟用服務發現時才用得上。其中必選參數為發送服務發現消息的組播地址(multicast)、端口(port)和協議(protocol)。其他參數決定 offer messages 的頻率、延遲等等。

    注意:需確保設備已配置為接收組播消息(例如,通過route add -nv 224.224.224.245 dev ens33 或類似配置)。

    再來看下客戶端配置示例:

    {

       "unicast" : "192.168.24.129",

       "logging" :

       {

           "level" : "debug",

           "console" : "true",

           "file" : { "enable" : "false", "path" : "/var/log/vsomeip.log" },

           "dlt" : "false"

       },

       "applications" :

       [

           {

               "name" : "Hello",

               "id" : "0x1313"

           }

       ],

       "routing" : "Hello",

       "service-discovery" :

       {

           "enable" : "true",

           "multicast" : "224.224.224.245",

           "port" : "30490",

           "protocol" : "udp",

           "initial_delay_min" : "10",

           "initial_delay_max" : "100",

           "repetitions_base_delay" : "200",

           "repetitions_max" : "3",

           "ttl" : "3",

           "cyclic_offer_delay" : "2000",

           "request_response_delay" : "1500"

       }

    }

    接下來在兩臺虛擬機上測試一下之前的 3 個示例是否都可以正常運行。

    下面的幾個 Tips 記錄了在實踐時遇到的問題及解決方案。

    Tips 1:

    在兩臺虛擬機上測試“第一個示例演示”的時候,如果將配置文件放在可執行文件同目錄的時候配置并不生效,那就通過以下方式指定配置文件

    VSOMEIP_CONFIGURATION=./vsomeip-local.json ./service_example

    使用 Wireshark 對 Vmware Network Adapter VMnet8 進行抓包,可見通信正常:

    Tips 2:

    在測試 “Request/Response 示例”的時候,出現的問題是:

    Request/Response 示例中雖然客戶端可以檢測到服務器端程序上線可用了,但是它們不互相發送 payload。

    本來以為是沒有添加靜態路由,但是執行route add -nv 224.224.224.245 dev ens33 后問題還是存在。

    參考https://github.com/COVESA/vsomeip/issues/44 中的一條評論,這個問題出現的原因在客戶端代碼中的 on_availability 函數。

    void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {

       std::cout << "CLIENT: Service ["

               << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance

               << "] is "

               << (_is_available ? "available." : "NOT available.")

               << std::endl;

       condition.notify_one();

    }

    當客戶端和服務都在同一臺計算機上時,運行程序沒有問題。但是當程序運行在兩臺機器上時,需要修改代碼如下:

    void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {

       std::cout << "CLIENT: Service ["

               << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance

               << "] is "

               << (_is_available ? "available." : "NOT available.")

               << std::endl;

       if(_is_available) {

         condition.notify_one();

       }

    }

    使用 Wireshark 對 Vmware Network Adapter VMnet8 進行抓包,通信正常:

    Tips 3:

    在測試“Subscribe/Notify 示例”的時候,需要在服務端的配置文件中添加 event 和 eventgroup 才可以。

    服務端的配置文件如下:


    {

       "unicast" : "192.168.24.132",

       "logging" :

       {

           "level" : "debug",

           "console" : "true",

           "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },

           "dlt" : "false"

       },

       "applications" :

       [

           {

               "name" : "World",

               "id" : "0x1212"

           }

       ],

       "services" :

       [

           {

               "service" : "0x1234",

               "instance" : "0x5678",

               "unreliable" : "30509",

               "events" :

               [

                   {

                       "event" : "0x4444",

                       "is_field" : "false",

                       "update-cycle" : 2000,

                       "is_reliable" : "false"

                   }

               ],

               "eventgroups" :

               [

                   {

                       "eventgroup" : "0x3333",

                       "events" : [ "0x4444" ],

                       "is_multicast" : "true"                                       

                   }

               ]

           }

       ],

       "routing" : "World",

       "service-discovery" :

       {

           "enable" : "true",

           "multicast" : "224.224.224.245",

           "port" : "30490",

           "protocol" : "udp",

           "initial_delay_min" : "10",

           "initial_delay_max" : "100",

           "repetitions_base_delay" : "200",

           "repetitions_max" : "3",

           "ttl" : "3",

           "cyclic_offer_delay" : "2000",

           "request_response_delay" : "1500"

       }

    }

    使用 wireshark 對 Vmware Network Adapter VMnet8 進行抓包,通信正常:

    參考鏈接:

    1.https://github.com/COVESA/vsomeip/wiki/vsomeip-in-10-minutes vsomeip官方文檔

    2.https://github.com/COVESA/vsomeip/wiki/vsomeip-in-10-minutes#protocol

    3.https://zhuanlan.zhihu.com/p/405534988

    4.vsomeip開源項目跑通過程 | 碼農家園

    5.[someip專題]vsomeip使用以及代碼解析1_AgingMoon的博客-CSDN博客_vsomeip

    6.快速上手 vsomeip

    軟件開放源代碼
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    使用開源軟件的專利侵權風險來源于內部、外部兩個方面。這些案件后來多以雙方簽訂了專利許可協議,向微軟支付專利許可費的方式達成了和解。
    常用日志分析軟件
    2021-10-13 06:34:58
    現在有大量的開放源碼日志跟蹤程序和分析工具可用,這使得為活動志書選擇合適的資源比想象中要容易得多。自由開放源代碼軟件社區提供了適用于各種網站以及幾乎所有操作系統的日志設計,下面給大家推薦三種最常用也是最好用的日志分析軟件
    因為 Graylog易于擴展,它在系統管理員中獲得了很好的聲譽。在出現安全性或性能事件時, IT管理員希望能夠盡快追查出癥狀的根源。在 Graylog中的搜索特性使得這一工作非常容易。NagiosLogserver引擎將實時地捕捉數據,并將其用于功能強大的搜索工具。該軟件能審核一系列網絡相關事件,幫助您自動發布警報。
    編者按:11月30日,工業和信息化部連續發布了《“十四五”信息化和工業化深度融合發展規劃》《“十四五”軟件和信息技術服務業發展規劃》《“十四五”大數據產業發展規劃》,中國電子報約請相關行業專家就三個產業發展規劃進行深度解讀,敬請期待。本期為國家工業信息安全發展研究中心主任趙巖對《“十四五”軟件和信息技術服務業發展規劃》的解讀。
    近日,安識科技A-Team團隊監測到Google Chrome V8類型混淆漏洞的細節,漏洞編號為CVE-2022-4262,這些漏洞可能導致瀏覽器崩潰或執行任意代碼。對此,安識科技建議廣大用戶及時升級到安全版本,并做好資產自查以及預防工作,以免遭受黑客攻擊。
    4 月 16 日消息 2022 年 04 月 14 日,Google 官方發布了一則 C
    微軟補丁日,有一個漏洞CVSS評分9.8
    近年來,通過這些惡意軟件竊取的敏感信息在暗網上大肆銷售,造成了巨大影響和危害。在新冠疫情期間,由于居家辦公措施的實施,攻擊者通過疫情主題的釣魚郵件投遞 Agent Tesla 和 Hawkeye 這兩種鍵盤記錄器。Genesis Store 在2020年利用 AZORult 獲取目標主機的敏感信息。此外,隨著居家辦公措施的流行,遠程登錄場景變得非常普遍。購買付費的安全解決方案,掃描系統中存在的漏洞并進行修復。監控系統驅動和注冊表的可疑變化,重點是對鍵盤輸入的捕獲。
    白皮書分析總結了過去一年開源生態發展特點、開源社區運營關鍵因素、開源商業模式與傳統行業開放創新的價值、開源風險點與治理規則、開源生態發展趨勢等。
    隨著整個社會加速數字化轉型步伐,開源產業發展進一步提速,開源產業生態構建、開源治理、行業開源等話題受到高度關注。當前,我國開源產業生態現狀如何?哪些產業趨勢和技術趨勢不容忽視?
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类