POCO库是强大的的跨平台C++库,可以用来编写多平台的网络应用程序,这些平台包括桌面端、服务端、移动端、IOT(物联网)、嵌入式系统等。总的来说是一个非常强大的综合性库。
1.支持跨平台
2.性能表现优异
3.API使用方便,便于上手
4.库可以拆分使用,容易实现轻量化调用
5.功能模块丰富
6.Poco C++库是在Boost软件许可证下授权的,既可以用来开发非商业应用,也可以用来开发商业应用。可以说是可以自由使用的了。
根据Poco官方文档介绍Poco库支持的功能组如下:
1.类型和字节序操作
2.错误处理和调试
3.内存管理
4.字符串和文本的格式化
5.平台和环境的操作和处理
6.随机数生成和各种哈希算法
7.时间和日期处理
8.文件操作系统处理
9.通知和事件
10.各种流处理
11.日志操作
12.动态的库操作
13.进程管理
14.url和uuid的生成和操作
15.XML和Json文件操作
16.网络编程
17.客户端程序和网络程序的编写
18.文件系统的支持和配置
19.日志系统的配置
总的来说就是能用到的功能poco库都支持,可以说是非常强大了。
源码下载和库编译?
Poco库的官网地址
https://pocoproject.org/index.html
Poco库的项目地址
https://github.com/pocoproject/poco/tree/master
Poco库可以根据使用需求不同,编译成静态库或者动态库,编译方法很简单,这里就不再做详细介绍了。
Poco库常用功能:
MD5值计算、Base64加密计算、HMAC-MD5计算
#include
#include
#include
//MD5值的计算
#include "Poco\MD5Engine.h"
#include "Poco\DigestStream.h"
#include "Poco\StreamCopier.h"
using Poco::DigestEngine;
using Poco::MD5Engine;
using Poco::DigestOutputStream;
using Poco::StreamCopier;
//base64的计算
#include "Poco\Base64Decoder.h"
#include "Poco\StreamCopier.h"
#include "Poco\Base64Encoder.h"
using Poco::Base64Encoder;
using Poco::StreamCopier;
using Poco::Base64Decoder;
//计算HMAC-MD5值
#include "Poco/HMACEngine.h"
#include "Poco/MD5Engine.h"
#include "Poco/DigestStream.h"
#include "Poco/StreamCopier.h"
#include
#include
using Poco::DigestEngine;
using Poco::HMACEngine;
using Poco::MD5Engine;
using Poco::DigestOutputStream;
using Poco::StreamCopier;
using namespace std;
int main(int argc, char** argv)
{
//计算文件的MD5值
ifstream inputStream("test.txt", ios::binary);
MD5Engine md5;
DigestOutputStream dos(md5);
StreamCopier::copyStream(inputStream, dos);
dos.close();
cout << DigestEngine::digestToHex(md5.digest()) << std::endl;
cout << "完成md5值的计算" << endl;
//计算字符串的MD5值
std::string INPUT_STRING = "hello";
stringstream stringStream(INPUT_STRING);
StreamCopier::copyStream(stringStream, dos);
dos.close();
cout << DigestEngine::digestToHex(md5.digest()) << std::endl;
cout << "字符串md5值计算完毕" << endl;
//对文件进行base64加密
ifstream base64EncodeInputStream("test.txt", ios::binary);
ofstream base64EncodeOutputStream("encoderesult.txt");
Base64Encoder encoder(base64EncodeOutputStream);
StreamCopier::copyStream(base64EncodeInputStream, encoder);
cout << "完成base64加密" << endl;
encoder.close();
//对文件进行解密
ofstream base64DecodeOutputStream("decoderesult.txt");
ifstream base64DecodeInputStream("encoderesult.txt");
Base64Decoder decoder(base64DecodeInputStream);
StreamCopier::copyStream(decoder,base64DecodeOutputStream);
//对字符串进行加密
stringstream strbase64encodeinputstream(string("ceshibase64"));
string strbase64encodeoutputStr;
stringstream strencodeOutputStream;
Base64Encoder stringencodr(strencodeOutputStream);
StreamCopier::copyStream(strbase64encodeinputstream, stringencodr);
stringencodr.close();
strencodeOutputStream >> strbase64encodeoutputStr;
//对字符串进行解密
stringstream strdecodeInputstream(strbase64encodeoutputStr);
stringstream strdecodeOutputstream;
string decodeResult;
Base64Decoder stringdecoder(strdecodeInputstream);
StreamCopier::copyStream(stringdecoder, strdecodeOutputstream);
strdecodeOutputstream >> decodeResult;
//计算文件的HMAC-MD5值
string passphrase("hmac-key");
ifstream hmacinputStream("test.txt", ios::binary);
HMACEngine hmac(passphrase);
DigestOutputStream hmacdos(hmac);
StreamCopier::copyStream(hmacinputStream, hmacdos);
hmacdos.close();
cout << DigestEngine::digestToHex(hmac.digest()) << std::endl;
//计算字符串的HMAC-MD5值
stringstream hmacStrinputStream("ceshishiyong");
HMACEngine hStrmac(passphrase);
DigestOutputStream hmaStrcdos(hStrmac);
StreamCopier::copyStream(hmacStrinputStream, hmaStrcdos);
hmaStrcdos.close();
cout << DigestEngine::digestToHex(hStrmac.digest()) << std::endl;
}
服务的程序类似于一个线程池程序,每个人物都是是一个子线程运行在对应的线程池当中。线程池的程序类似于下面:
#include "Poco/Util/ServerApplication.h"
#include "Poco/Logger.h"
class MyServer : public Poco::Util::ServerApplication
{
public:
MyServer();
virtual ~ MyServer();
// Poco::Util::ServerApplication overridables
public:
virtual void initialize(Poco::Util::Application &self) override;
virtual void uninitialize() override;
virtual int main(const std::vector& args) override;
private:
void createLogDir();
};
线程池管理器就是所谓的服务器主程序,主程序继承自Poco::Utils::ServerApplication
主要重写三个接口
//initialize是初始化接口,在初始化服务器的时候被调用,做些初始化操作
virtual void initialize(Poco::Util::Application &self) override;
//uninitialize是清理操作,在服务器终止的时候被调用,做一些清理的操作
virtual void uninitialize() override;
//main是主函数主要负责对应的主程序
virtual int main(const std::vector& args) override;
#include "MyServer.h"
#include "Poco/TaskManager.h"
#include "Poco/AutoPtr.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/FileChannel.h"
#include "Poco/SplitterChannel.h"
#include "Poco/FormattingChannel.h"
#include "Poco/PatternFormatter.h"
#include "Poco/SimpleFileChannel.h"
#include
#include
#include
void MyServer::initialize(Poco::Util::Application &self)
{
ServerApplication::initialize(self);
logger().information("Service is starting up");
}
void MyServer::uninitialize()
{
logger().information("Service is shutting down");
ServerApplication::uninitialize();
}
int MyServer::main(const std::vector& args)
{
HANDLE hMutext = CreateMutexA(NULL, TRUE, " My-service-mutext");
logger().information("Service is running as %s ...",
config().getBool("application.runAsService", false)
? std::string("service") : std::string("command line"));
Poco::TaskManager taskManager;
//版本更新
taskManager.start(new UpdateTask());
//等待任务取消
waitForTerminationRequest();
taskManager.cancelAll();
//等待取消操作完成
taskManager.joinAll();
ReleaseMutex(hMutext);
hMutext = INVALID_HANDLE_VALUE;
return Application::EXIT_OK;
}
服务器中的每个人物都是一个线程类似于QT中的QRunnable
Poco中的程序中的每一个人物都继承于Task类,
#include "Poco/Task.h"
class MyUpdateTask : public Poco::Task
{
public:
MyUpdateTask();
virtual ~ MyUpdateTask();
// Poco::Task overridables
public:
//runTask是入口函数
virtual void runTask() override;
private:
};
主函数中启动服务程序的方法
#include "MyServer.h"
#include
#ifdef _DEBUG
int main()
{
HYPYServer server;
server.main(std::vector());
return 0;
}
#else
POCO_SERVER_MAIN(HYPYServer)
#endif
bool UpdateTask::fetchUpdateInfoFromHTTPServer()
{
//请求的参数
std::string arg1 = "1";
std::string arg2 = "2";
std::string arg3 = "3";
//拼接对应的请求
Config config;
std::string path = "/api/v1/update";
Poco::URI uri;
uri.setScheme(config.getServerScheme());
uri.setHost(config.getServerAddr());
uri.setPort(config.getServerPort());
uri.setPath(path);
uri.addQueryParameter("arg1", arg1);
uri.addQueryParameter("arg2", arg2);
uri.addQueryParameter("arg3", arg3);
Poco::Net::HTTPSClientSession* https_session = OSUtils::CommonUtils::GetHttpsClientSession();
https_session->setPort(uri.getPort());
https_session->setHost(uri.getHost());
std::string pathAndQuery(uri.getPathAndQuery());
Poco::Net::HTTPRequest request(
Poco::Net::HTTPRequest::HTTP_GET, pathAndQuery,
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPResponse response;
https_session->sendRequest(request);
std::istream &streamIn = https_session->receiveResponse(response);
std::ostringstream responseStream;
Poco::StreamCopier::copyStream(streamIn, responseStream);
m_responseContent = responseStream.str();
delete https_session;
https_session = nullptr;
return response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK;
}
int MyUpdateTask::UpdateWork(std::string loginid, std::string clientid, std::string& filePath)
{
try
{
Config config;
std::string path = "/api/v1/dict/download";
Poco::URI uri;
uri.setScheme(config.getServerScheme());
uri.setHost(config.getServerAddr());
uri.setPort(config.getServerPort());
uri.setPath(path);
Poco::Net::HTTPSClientSession* https_session = OSUtils::CommonUtils::GetHttpsClientSession();
https_session->setHost(uri.getHost());
https_session->setPort(uri.getPort());
Poco::Net::HTTPRequest request(
Poco::Net::HTTPRequest::HTTP_POST, uri.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTMLForm form;
form.add("loginid", loginid);
form.add("clientid", clientid);
form.prepareSubmit(request);
form.write(https_session->sendRequest(request));
Poco::Net::HTTPResponse response;
std::istream &streamIn = https_session->receiveResponse(response);
if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK)
{
delete https_session;
https_session = nullptr;
return 1;
}
std::ostringstream responseStream;
Poco::StreamCopier::copyStream(streamIn, responseStream);
std::string resultStr = responseStream.str();
delete https_session;
https_session = nullptr;
Poco::JSON::Parser parser;
auto root = parser.parse(resultStr);
Poco::JSON::Object::Ptr objRoot = root.extract();
if (!objRoot)
return 2;
int codeResult = objRoot->getValue("code");
if (codeResult == 200)
{
dictFilePath = objRoot->getValue("result");
return 0;
}
return codeResult;
}
catch (...)
{
return 1;
}
}
int MyUpdateTask::UpdateWork(std::string loginid, std::string clientid, std::string path)
{
try
{
//获得对应的请求参数
Config config;
std::string path = "/api/v1/dict/ceshi";
Poco::URI uri;
uri.setScheme(config.getServerScheme());
uri.setHost(config.getServerAddr());
uri.setPort(config.getServerPort());
uri.setPath(path);
//获得对应的会话客户端
Poco::Net::HTTPSClientSession* https_session = OSUtils::CommonUtils::GetHttpsClientSession();
https_session->setHost(uri.getHost());
https_session->setPort(uri.getPort());
//生成对应的请求
Poco::Net::HTTPRequest request(
Poco::Net::HTTPRequest::HTTP_POST, uri.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);
request.setContentType("multipart/form-data");
//在表单中添加对应的参数和文件
Poco::Net::HTMLForm form;
form.setEncoding(Poco::Net::HTMLForm::ENCODING_MULTIPART);
form.add("loginid", loginid);
form.add("clientid", clientid);
form.addPart("dict", new Poco::Net::FilePartSource(path));
form.prepareSubmit(request);
form.write(https_session->sendRequest(request));
Poco::Net::HTTPResponse response;
std::istream &streamIn = https_session->receiveResponse(response);
if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK)
{
delete https_session;
https_session = nullptr;
return 1;
}
std::ostringstream responseStream;
Poco::StreamCopier::copyStream(streamIn, responseStream);
std::string resultStr = responseStream.str();
delete https_session;
https_session = nullptr;
Poco::JSON::Parser parser;
auto root = parser.parse(resultStr);
Poco::JSON::Object::Ptr objRoot = root.extract();
if (!objRoot)
return 2;
int codeResult = objRoot->getValue("code");
if(codeResult == 200)
{
return 0;
}
return codeResult;
}
catch (...)
{
return 1;
}
}
Poco::URI uri(addrs.at(index).fileUrl);
Poco::Net::HTTPSClientSession* https_session = OSUtils::CommonUtils::GetHttpsClientSession();
https_session->setPort(uri.getPort());
https_session->setHost(uri.getHost());
Poco::Net::HTTPRequest request(
Poco::Net::HTTPRequest::HTTP_GET, uri.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPResponse response;
https_session->sendRequest(request);
std::istream &streamIn = https_session->receiveResponse(response);
if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK)
{
}
Poco::Net::HTTPSClientSession* OSUtils::CommonUtils::GetHttpsClientSession()
{
std::string certificate_path = OSUtils::PathUtils::getCertificatePath();
SSLManager::InvalidCertificateHandlerPtr handlerPtr(new AcceptCertificateHandler(false));
Context::Ptr context = new Context(Context::TLSV1_2_CLIENT_USE, certificate_path, Poco::Net::Context::VERIFY_NONE, 9);
SSLManager::instance().initializeClient(nullptr, handlerPtr, context);
HTTPSClientSession *session = new HTTPSClientSession(context);
session->setTimeout(5000 * 1000);
int timeout_sec = session->getTimeout().seconds();
return session;
}
ifstream instream(filepath, ios::binary);
Poco::Zip::Decompress decompress(instream, fileDir);
decompress.decompressAllFiles();
instream.close();
File zip_file(filepath);
if (zip_file.exists())
zip_file.remove();