【C++】POCO學習總結(十):Poco::Util::Application(應用程序框架)

【C++】郭老二博文之:C++目錄

1、Poco::Util::Application 應用框架

1.1 應用程序基本功能

Poco::Util::Application是POCO實現的的應用程序框架,支持功能如下:

  • 命令行參數處理
  • 配置文件
  • 初始化和關機
  • 日志

1.2 命令行程序和守護進程

POCO支持兩種應用:

  • 命令行應用程序:從命令行啟動,POCO支持命令行參數處理
  • 服務器應用程序:通常作為守護進程運行,比如Linux守護進程、Windows服務

2、Poco::Util::Subsystem 子系統

2.1 說明

Poco::Util::Application繼承自Poco::Util::Subsystem。
POCO中將不同的子系統組成一個應用程序。子系統以模塊化的方式擴展應用。

  • 子系統抽象出統一的初始化和關閉等步驟。
  • 當一個應用程序被初始化時,它所有注冊的子系統也被初始化。
  • 當一個應用程序關閉時,它所有注冊的子系統也會關閉。

2.2 使用

一個子系統都是從Poco::Util::Subsystem繼承而來,下面列出幾個常用的接口

  • const char* name():返回子系統的名稱;
  • void initialize(Application& app):初始化子系統操作;
  • void uninitialize(Application& app):關閉子系統時的操作;
  • void reinitialize(Application& app):重新配置子系統(可選;默認實現調用uninitialize(),然后調用initialize());
  • void defineOptions(OptionSet& options):子系統自定義命令行參數

3、命令行程序

命令行應用程序是通過創建Poco::Util::Application的子類來實現的。有幾個虛成員函數需要重寫:

  • void initialize(Application& self)
  • void reinitialize()
  • void uninitialize()
  • void defineOptions()
  • int main(std::vectorstd::string& args)

注意:上面的main是Poco::Util::Application的成員函數,應用程序的主要邏輯寫在這里。
返回值是枚舉:ExitCode

enum ExitCode
{EXIT_OK          = 0,   成功終止EXIT_USAGE	     = 64,  命令行使用錯誤EXIT_DATAERR     = 65,  數據格式錯誤EXIT_NOINPUT     = 66,  無法打開輸入EXIT_NOUSER      = 67,  地址錯誤EXIT_NOHOST      = 68,  主機名是未知EXIT_UNAVAILABLE = 69,  服務不可用EXIT_SOFTWARE    = 70,  內部軟件錯誤EXIT_OSERR	     = 71,  系統錯誤 (e.g., can't fork)EXIT_OSFILE      = 72,  關鍵操作系統文件丟失EXIT_CANTCREAT   = 73,  不能創建(用戶)輸出文件EXIT_IOERR       = 74,  輸入/輸出錯誤EXIT_TEMPFAIL    = 75,  臨時錯誤,可以嘗試重新運行EXIT_PROTOCOL    = 76,  協議中的遠程錯誤EXIT_NOPERM      = 77,  沒有權限EXIT_CONFIG      = 78   配置錯誤
};

4、Poco::Util::ServerApplication 服務類程序

想要實現一個服務類程序,需要從Poco::Util::ServerApplication繼承;
Poco::Util::ServerApplication本身繼承自Poco::Util::Application;

服務類應用程序可以從命令行運行,比如:Linux守護進程、Windows服務。
通常,服務類應用程序在后臺線程中工作。因此,main()成員函數將啟動線程,然后等待外部請求來終止應用程序(參見waitForTerminationRequest())。

5、配置文件

5.1 說明

默認情況下會創建兩個配置:

  • 可寫的MapConfiguration,只讀的PRIO_APPLICATION
  • SystemConfiguration, PRIO_SYSTEM

5.2 用法

void MyApplication::initialize(Application& self)
{loadConfiguration(); // 加載默認配置文件Application::initialize(self);
}

6、命令行參數

6.1 說明

應用程序可以定義和處理命令行參數(選項)。命令行參數格式隨系統不同而不同:

  • Windows:/option or /option=value
  • Linux:-o, -ovalue, --option or --option:value

6.2 使用

應用程序的選項通過重寫虛函數 void defineOptions(OptionSet& options) 來實現
“定義選項類”OptionSet 用來處理選項,比如OptionSet::addOption()函數可以添加選項,示例如下:

void defineOptions(OptionSet& options)
{Application::defineOptions(options);options.addOption(Option("help", "h", "display help information on command line arguments").required(false).repeatable(false).callback(OptionCallback<SampleApp>(this, &SampleApp::handleHelp)));options.addOption(Option("config-file", "f", "load configuration data from a file").required(false).repeatable(true).argument("file").callback(OptionCallback<SampleApp>(this, &SampleApp::handleConfig)));options.addOption(Option("bind", "b", "bind option value to test.property").required(false).argument("value").validator(new IntValidator(0, 100)).binding("test.property"));
}

運行時打印:

-h, --help display help 	information on command line arguments
-ffile, --config-file=file 	load configuration data from a file
-bvalue, --bind=value bind 	option value to test.property

每個選項Option有如下內容:

  • 一個全名
  • 一個用字符表示的縮寫(短名字)
  • 一段描述
  • 一個參數名:argument
  • 是否必須:required
  • 是否可重復:repeatable,它可以在命令行中被多次給出
  • 回調函數:callback

6.3 驗證選項參數

通過為選項指定一個Validator對象,可以自動驗證選項參數。

  • IntValidator 檢查參數是否為一定范圍內的整數。
  • RegExpValidator 驗證參數是否匹配給定的正則表達式。

比如上例中的:.validator(new IntValidator(0, 100))

6.4 顯示幫助信息

Poco::Util::HelpFormatter類可用于顯示命令行選項幫助信息。
當用戶請求幫助信息時,應取消所有進一步的命令行處理(特別是強制執行所需選項)。這可以通過調用stopOptionsProcessing()來完成。

void displayHelp()
{HelpFormatter helpFormatter(options());helpFormatter.setCommand(commandName());helpFormatter.setUsage("OPTIONS");helpFormatter.setHeader("Poco::Util::Application類的示例");helpFormatter.format(std::cout);
}void handleHelp(const std::string& name, const std::string& value)
{_helpRequested = true;displayHelp();stopOptionsProcessing();
}

7、Windows 服務

Windows服務需要注冊。
Poco::Util::ServerApplication可以實現注冊的步驟。

  • 注冊:在命令行啟動時指定選項 /registerService
  • 取消注冊:指定 /unregisterService 選項來取消
  • 設置服務名稱:通過選項 /displayName 來指定

8、Linux 守護進程

在Linux平臺上,繼承Poco::Util::ServerApplication后,可以通過命令行參數“–daemon”來實現,作為守護進程運行。
一個守護進程,當啟動時,會立即從執行實際工作的后臺進程中分離出來。啟動后臺進程后,前臺進程退出。
初始化完成后,在進入main()方法之前,守護進程的當前工作目錄將更改為根目錄(“/”),這是守護進程的常見做法。

應用程序可以通過檢查application.runasdaemon配置屬性來確定它是否作為守護進程運行。
與Windows服務一樣,在配置文件中使用相對路徑時要小心,因為守護進程的當前工作目錄是根目錄。

#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Task.h"
#include "Poco/TaskManager.h"
#include "Poco/DateTimeFormatter.h"
#include <iostream>using Poco::Util::Application;
using Poco::Util::ServerApplication;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::OptionCallback;
using Poco::Util::HelpFormatter;
using Poco::Task;
using Poco::TaskManager;
using Poco::DateTimeFormatter;class SampleTask: public Task
{
public:SampleTask(): Task("SampleTask"){}void runTask(){Application& app = Application::instance();while (!sleep(5000)){Application::instance().logger().information("busy doing nothing... " + DateTimeFormatter::format(app.uptime()));}}
};class SampleServer: public ServerApplication
{
public:SampleServer(): _helpRequested(false){}~SampleServer(){}protected:void initialize(Application& self){loadConfiguration(); // load default configuration files, if presentServerApplication::initialize(self);logger().information("starting up");}void uninitialize(){logger().information("shutting down");ServerApplication::uninitialize();}void defineOptions(OptionSet& options){ServerApplication::defineOptions(options);options.addOption(Option("help", "h", "display help information on command line arguments").required(false).repeatable(false).callback(OptionCallback<SampleServer>(this, &SampleServer::handleHelp)));}void handleHelp(const std::string& name, const std::string& value){_helpRequested = true;displayHelp();stopOptionsProcessing();}void displayHelp(){HelpFormatter helpFormatter(options());helpFormatter.setCommand(commandName());helpFormatter.setUsage("OPTIONS");helpFormatter.setHeader("A sample server application that demonstrates some of the features of the Util::ServerApplication class.");helpFormatter.format(std::cout);}int main(const ArgVec& args){if (!_helpRequested){TaskManager tm;tm.start(new SampleTask);waitForTerminationRequest();tm.cancelAll();tm.joinAll();}return Application::EXIT_OK;}
private:bool _helpRequested;
};POCO_SERVER_MAIN(SampleServer)

9、一個簡單的示例

#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/AutoPtr.h"
#include <iostream>
#include <sstream>using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Util::AbstractConfiguration;
using Poco::Util::OptionCallback;
using Poco::AutoPtr;class SampleApp: public Application/// This sample demonstrates some of the features of the Util::Application class,/// such as configuration file handling and command line arguments processing.////// Try SampleApp --help (on Unix platforms) or SampleApp /help (elsewhere) for/// more information.
{
public:SampleApp(): _helpRequested(false){}protected:void initialize(Application& self){loadConfiguration(); // load default configuration files, if presentApplication::initialize(self);// add your own initialization code here}void uninitialize(){// add your own uninitialization code hereApplication::uninitialize();}void reinitialize(Application& self){Application::reinitialize(self);// add your own reinitialization code here}void defineOptions(OptionSet& options){Application::defineOptions(options);options.addOption(Option("help", "h", "display help information on command line arguments").required(false).repeatable(false).callback(OptionCallback<SampleApp>(this, &SampleApp::handleHelp)));options.addOption(Option("define", "D", "define a configuration property").required(false).repeatable(true).argument("name=value").callback(OptionCallback<SampleApp>(this, &SampleApp::handleDefine)));options.addOption(Option("config-file", "f", "load configuration data from a file").required(false).repeatable(true).argument("file").callback(OptionCallback<SampleApp>(this, &SampleApp::handleConfig)));options.addOption(Option("bind", "b", "bind option value to test.property").required(false).repeatable(false).argument("value").binding("test.property"));}void handleHelp(const std::string& name, const std::string& value){_helpRequested = true;displayHelp();stopOptionsProcessing();}void handleDefine(const std::string& name, const std::string& value){defineProperty(value);}void handleConfig(const std::string& name, const std::string& value){loadConfiguration(value);}void displayHelp(){HelpFormatter helpFormatter(options());helpFormatter.setCommand(commandName());helpFormatter.setUsage("OPTIONS");helpFormatter.setHeader("A sample application that demonstrates some of the features of the Poco::Util::Application class.");helpFormatter.format(std::cout);}void defineProperty(const std::string& def){std::string name;std::string value;std::string::size_type pos = def.find('=');if (pos != std::string::npos){name.assign(def, 0, pos);value.assign(def, pos + 1, def.length() - pos);}else name = def;config().setString(name, value);}int main(const ArgVec& args){if (!_helpRequested){logger().information("Command line:");std::ostringstream ostr;for (ArgVec::const_iterator it = argv().begin(); it != argv().end(); ++it){ostr << *it << ' ';}logger().information(ostr.str());logger().information("Arguments to main():");for (ArgVec::const_iterator it = args.begin(); it != args.end(); ++it){logger().information(*it);}logger().information("Application properties:");printProperties("");}return Application::EXIT_OK;}void printProperties(const std::string& base){AbstractConfiguration::Keys keys;config().keys(base, keys);if (keys.empty()){if (config().hasProperty(base)){std::string msg;msg.append(base);msg.append(" = ");msg.append(config().getString(base));logger().information(msg);}}else{for (AbstractConfiguration::Keys::const_iterator it = keys.begin(); it != keys.end(); ++it){std::string fullKey = base;if (!fullKey.empty()) fullKey += '.';fullKey.append(*it);printProperties(fullKey);}}}private:bool _helpRequested;
};

打印幫助信息

$ ./SampleApp -h
usage: SampleApp OPTIONS
A sample application that demonstrates some of the features of the Poco::Util::Application class.-h, --help                         display help information on command line arguments
-Dname=value, --define=name=value  define a configuration property
-ffile, --config-file=file         load configuration data from a file
-bvalue, --bind=value              bind option value to test.property

運行后的打印信息

$ ./SampleApp
[Information] Command line:
[Information] ./SampleApp 
[Information] Arguments to main():
[Information] Application properties:
[Information] application.argc = 1
[Information] application.argv[0] = ./SampleApp
[Information] application.baseName = SampleApp
[Information] application.cacheDir = /home/laoer/.cache/SampleApp/
[Information] application.configDir = /home/laoer/git/poco/Util/samples/SampleApp/
[Information] application.dataDir = /home/laoer/.local/share/SampleApp/
[Information] application.dir = /home/laoer/git/poco/Util/samples/SampleApp/bin/Linux/x86_64/
[Information] application.name = SampleApp
[Information] application.path = /home/laoer/git/poco/Util/samples/SampleApp/bin/Linux/x86_64/SampleApp
[Information] application.tempDir = /home/laoer/.local/tmp/SampleApp/
[Information] logging.channels.c1.class = ConsoleChannel
[Information] logging.channels.c1.formatter = f1
[Information] logging.formatters.f1.class = PatternFormatter
[Information] logging.formatters.f1.pattern = [%p] %t
[Information] logging.loggers.app.channel = c1
[Information] logging.loggers.app.name = Application
[Information] logging.loggers.root.channel.class = ConsoleChannel
[Information] system.osName = Linux
[Information] system.osVersion = 6.2.0-37-generic
[Information] system.osArchitecture = x86_64
[Information] system.nodeName = laoer
[Information] system.nodeId = 
[Information] system.currentDir = /home/laoer/git/poco/Util/samples/SampleApp/bin/Linux/x86_64/
[Information] system.homeDir = /home/laoer/
[Information] system.configHomeDir = /home/laoer/.config/
[Information] system.cacheHomeDir = /home/laoer/.cache/
[Information] system.dataHomeDir = /home/laoer/.local/share/
[Information] system.tempHomeDir = /home/laoer/.local/tmp/
[Information] system.tempDir = /tmp/
[Information] system.configDir = /etc/
[Information] system.dateTime = 2023-12-10T14:50:02Z
[Information] system.pid = 4919

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/212473.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/212473.shtml
英文地址,請注明出處:http://en.pswp.cn/news/212473.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java架構師系統架構實現高內聚低耦合

目錄 1 導語2 邊界內聚耦合概述3 聚焦內聚4 關注耦合5 如何實現高內聚低耦合6 內聚耦合規劃不當的效果7 總結想學習架構師構建流程請跳轉:Java架構師系統架構設計 1 導語 架構設計的核心維度,從系統的擴展性、高性能、高可用、高安全性和伸縮性五個維度進行了探討,并介紹了…

【Docker】進階之路:(一)容器技術發展史

【Docker】進階之路&#xff1a;&#xff08;一&#xff09;容器技術發展史 什么是容器為什么需要容器容器技術的發展歷程Docker容器是如何工作的 什么是容器 容器作為一種先進的虛擬化技術&#xff0c;已然成為了云原生時代軟件開發和運維的標準基礎設施。在了解容器技術之前…

抖音本地生活服務商申請入口在哪里?具體流程是怎樣的?

不論是抖音的本地生活業務&#xff0c;還是后來的支付寶、視頻號的本地生活業務&#xff0c;因為市場體量足夠龐大&#xff0c;市場前景廣闊&#xff0c;一直很受各大創業者的追捧。那么&#xff0c;如此火熱的本地生活項目&#xff0c;想要申請成為服務商&#xff0c;具體的申…

列表標簽的介紹與使用

列表的作用&#xff1a; 整齊、整潔、有序&#xff0c;它作為布局會更加自由和方便。 根據使用情景不同&#xff0c;列表可以分為三大類&#xff1a;無序列表、有序列表和自定義列表 無序列表 <ul> 標簽表示 HTML 頁面中項目的無序列表&#xff0c;一般會以項目符號呈…

深入了解linux下網卡防火墻selinux

深入了解linux下網卡防火墻selinux 在Linux系統中&#xff0c;網絡安全是非常重要的。為了保護系統免受惡意攻擊和未經授權的訪問&#xff0c;我們可以使用防火墻來限制網絡流量。而在Linux下&#xff0c;我們可以使用SELinux&#xff08;Security-Enhanced Linux&#xff09;…

Java調試技巧之垃圾回收機制解析

Java作為一種高級編程語言&#xff0c;以其跨平臺、面向對象、自動內存管理等特性而廣受開發者的喜愛。其中&#xff0c;自動內存管理是Java的一大亮點&#xff0c;通過垃圾回收機制實現對內存的自動分配和釋放&#xff0c;極大地簡化了開發者的工作。本文將深入探討Java的垃圾…

mysql數據庫文件丟失恢復---惜分飛

客戶服務器重啟,mysql相關數據文件丟失 通過底層工具進行分析,無法正確恢復數據庫名字,一個個單個ibd文件(而且很多本身是錯誤的) 對于這種情況,通過mysql block掃描恢復出來page文件 恢復出來客戶需要數據 這個客戶出現該故障的原因大概率是由于文件系統損壞導致.最終…

C語言進階之路-數據結構篇

目錄 一、學習目標 二、數據結構 1.基本概念 線性關系&#xff1a; 非線性關系&#xff1a; 存儲形式 2. 算法分析 2.1 時間復雜度 2.2 空間復雜度 2.3 時空復雜度互換 總結 一、學習目標 了解數據結構的基本概念了解算法的分析方法 二、數據結構 1.基本概念 數據結…

測試bug分析

項目場景&#xff1a; 提示&#xff1a;這里簡述項目相關背景&#xff1a; 例如&#xff1a;項目場景&#xff1a;示例:通過藍牙芯片(HC-05)與手機 APP 通信&#xff0c;每隔 5s 傳輸一批傳感器數據(不是很大) 問題描述 提示&#xff1a;這里描述項目中遇到的問題&#xff1…

Nacos源碼解讀11——客戶端怎么讀取最新的配置信息

項目啟動怎么讀取的配置信息 自動裝配 SpringBoot 自動裝配機制 加載 WEB/INF spring.factories 會將如下幾個Bean加載到ioc 容器中 BeanConditionalOnMissingBeanpublic NacosConfigProperties nacosConfigProperties() {return new NacosConfigProperties();}BeanCondition…

【算法Hot100系列】兩數之和

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

【rabbitMQ】模擬work queue,實現單個隊列綁定多個消費者

上一篇&#xff1a; springboot整合rabbitMQ模擬簡單收發消息 https://blog.csdn.net/m0_67930426/article/details/134904766?spm1001.2014.3001.5502 在這篇文章的基礎上進行操作 基本思路&#xff1a; 1.在rabbitMQ控制臺創建一個新的隊列 2.在publisher服務中定義一個…

MySQL中的數據類型

MySQL中的數據類型 大家好&#xff0c;我是微賺淘客系統的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將探討MySQL中的數據類型&#xff0c;這是數據庫設計中至關重要的一部分。數據庫作為程序的底層支持&#xff0c;數據類型的選擇…

[python]利用whl輪子文件python3.12安裝talib

ta-lib目前很多人使用&#xff0c;網上也有很多人下載whl文件直接pip安裝即可&#xff0c;但是最新版本3.12沒有出來&#xff0c;因此本人獨家制作python 3.12版本whl文件&#xff0c;從源碼開始編譯生成。TA-Lib-0.4.28-cp312-cp312-win-amd64.whl &#xff0c;注意這個whl文件…

Java 多線程下的單例模式

單例對象&#xff08;Singleton&#xff09;是一種常用的設計模式。在Java應用中&#xff0c;單例對象能保證在一個JVM中&#xff0c;該對象只有一個實例存在。正是由于這個特 點&#xff0c;單例對象通常作為程序中的存放配置信息的載體&#xff0c;因為它能保證其他對象讀到一…

JWT的原理

在談及jwt原理前,我們其實對jwt并不陌生,對于有經驗的碼農,大都聽過或者實踐過,對于一些初學者,凡是談及安全方面的問題,總是覺得很復雜,感覺不是自己能搞得懂得,但其實無非也是加密解密的過程,不要想的太復雜,我們先說一說JWT在生產上的應用 JWT在生產上的應用 傳遞用戶身份信…

Android系統中使用Cunit測試C/C++接口

Android系統中使用Cunit測試C/C接口 Cunit是C/C語言的單元測試框架&#xff0c;但常用于Windows和Linux開發中。 Android系統中經常有jni、so庫、hal service等都是C/C實現&#xff0c;本文講解如何將Cunit嵌入Android中&#xff0c;用于測試一些C/C api。 Cunit簡介 Cunit是很…

全面解析“由于找不到hid.dll,無法繼續執行代碼”的4個解決方法

在計算機使用過程中&#xff0c;我們經常會遇到一些錯誤提示&#xff0c;其中之一就是“找不到hid.dll”。這個問題通常出現在嘗試運行某個程序或訪問某個設備時。那么&#xff0c;當我們遇到這個問題時&#xff0c;應該如何解決呢&#xff1f;本文將詳細介紹找不到hid.dll的解…

高校需要哪些大數據實訓平臺?

當前&#xff0c;數據已成為重要的生產要素&#xff0c;大數據產業作為以數據生成、采集、存儲、加工、分析、服務為主的戰略性新興產業&#xff0c;是激活數據要素潛能的關鍵支撐&#xff0c;是加快經濟社會發展質量變革、效率變革、動力變革的重要引擎。 泰迪大數據實驗…

Angular 14帶來了類型化表單和獨立組件

獨立組件通過減少對ngmodule的需求&#xff0c;有望簡化Angular應用的開發。 介紹 Angular 14是谷歌開發的、基于typescript的web應用框架的最新版本&#xff0c;它以輸入表單和獨立組件的開發者預覽版為特色。 其特性包括&#xff1a; 一個基于組件的框架&#xff0c;用于構…