Poco: 一个功能丰富、易于使用的跨平台C++开发框架(FTP上传下载、断点续传等)
目录
1.简介
2.功能模块
2.1.核心基础模块(必知)
2.2.网络与通信模块
2.3.数据处理模块
2.4.工具与辅助模块
2.5.其他实用模块
3.安装
3.1.Windows 安装(推荐 vcpkg,最简单)
3.2.Linux 安装(Ubuntu/Debian)
4.Poco 核心模块详细使用
5.与其他库的对比
1.简介
Poco是一个功能丰富、易于使用的跨平台C++开发框架,全称为"POrtable COmponents",它提供了一系列的类库和工具,用于开发跨平台、高性能、可扩展的应用程序。它的设计目标是提供 “即用型” 组件,简化 C++ 开发。它的模块划分清晰,覆盖了从基础工具到网络、数据库、加密等多种场景。
项目Github地址:https://github.com/pocoproject/poco
官网:https://pocoproject.org/
2.功能模块
2.1.核心基础模块(必知)
Foundation
Poco 的 “地基” 模块,所有其他模块的依赖项,提供最基础的工具类。
- 基本数据类型(如
Poco::Int32、Poco::UInt64)、跨平台类型定义(解决不同系统类型长度差异)。 - 字符串处理(
Poco::String工具类:trim、大小写转换、分割等)。 - 智能指针(
Poco::AutoPtr,用于管理对象生命周期,支持引用计数)。 - 日志系统(
Poco::Logger,支持控制台、文件、滚动日志等输出,分级日志(DEBUG/INFO/ERROR))。 - 文件与目录操作(
Poco::File、Poco::Path,跨平台处理文件路径、创建 / 删除 / 移动文件)。 - 异常体系(
Poco::Exception基类,所有 Poco 异常的父类,支持嵌套异常和错误信息)。 - 时间日期(
Poco::DateTime、Poco::Timestamp,处理时间戳、时区转换)。
2.2.网络与通信模块
1.Net
处理网络协议和通信的核心模块,支持 TCP/UDP、HTTP、FTP、SMTP 等。
- 底层 socket 封装(
Poco::Net::Socket、Poco::Net::StreamSocket,简化 TCP/UDP 通信)。 - HTTP 客户端 / 服务器(
Poco::Net::HTTPClientSession、HTTPServer,支持 GET/POST 等方法)。 - FTP 客户端(
Poco::Net::FTPClientSession,上传 / 下载 / 目录操作,支持被动模式)。 - 邮件协议(SMTP 发送邮件、POP3 接收邮件,
Poco::Net::SMTPClientSession)。 - 网络工具(
Poco::Net::DNS解析、Poco::Net::IPAddress处理 IP 地址)。
2.NetSSL_OpenSSL
基于 Net 模块,提供 SSL/TLS 加密通信支持(依赖 OpenSSL 库)。
- HTTPS 客户端 / 服务器(
Poco::Net::HTTPSClientSession,支持证书验证、加密传输)。 - 加密的 socket 通信(
Poco::Net::SecureStreamSocket,对 TCP 连接进行 SSL 加密)。 - 证书管理(加载 / 验证 SSL 证书、处理密钥)。
2.3.数据处理模块
1.Data
数据库访问抽象层,统一不同数据库的操作接口(支持多数据库适配)。
- 数据库连接管理(
Poco::Data::Session,统一连接字符串格式)。 - SQL 语句执行(
Poco::Data::Statement,支持参数绑定、批量操作)。 - 适配多种数据库:MySQL(
DataMySQL)、PostgreSQL(DataPostgreSQL)、SQLite(DataSQLite)、ODBC 等(需单独链接对应子模块)。
2.XML
XML 文档解析与生成模块,支持 DOM 和 SAX 两种解析模式。
- DOM 解析(
Poco::XML::Document、Element,内存中构建 XML 树,方便增删改查)。 - SAX 解析(
Poco::XML::SAXParser,流式解析,适合大文件,低内存占用)。 - XML 命名空间、属性处理、格式化输出。
3.JSON
JSON 数据的解析与生成(轻量、无依赖)。
- JSON 对象 / 数组(
Poco::JSON::Object、Array,类似字典和列表,支持嵌套)。 - 序列化 / 反序列化(
Poco::JSON::Parser解析 JSON 字符串为对象,Stringifier生成 JSON 字符串)。 - 支持数字、字符串、布尔、null 等类型,兼容标准 JSON 格式。
2.4.工具与辅助模块
1.Util
应用程序开发工具类,简化配置、命令行、服务化等场景。
- 配置文件处理(
Poco::Util::PropertyFileConfiguration处理 INI 格式配置,XMLConfiguration处理 XML 配置)。 - 命令行参数解析(
Poco::Util::OptionSet,定义参数规则并解析命令行输入)。 - 应用程序框架(
Poco::Util::Application,封装程序生命周期(初始化、运行、 cleanup),适合构建服务类程序)。
2.Crypto
加密与安全工具,提供哈希、加密算法和证书处理。
- 哈希算法(MD5、SHA-1、SHA-256 等,
Poco::Crypto::DigestEngine)。 - 对称加密(AES、DES 等,
Poco::Crypto::Cipher)。 - 非对称加密(RSA 密钥对生成、签名与验证)。
3.Zip
ZIP 压缩文件的创建与解压(支持密码保护)。
- 解压 ZIP 文件(
Poco::Zip::Decompress,提取单个或全部文件)。 - 创建 ZIP 文件(
Poco::Zip::Compress,添加文件 / 目录并压缩)。
2.5.其他实用模块
- Threads:多线程与同步工具(
Poco::Thread、Mutex、Condition,封装跨平台线程操作)。 - DateTimeFormatter/Parser:时间日期格式化与解析(将
DateTime转为字符串,或从字符串解析为DateTime)。 - UUID:生成 UUID(唯一标识符,
Poco::UUIDGenerator)。 - 文件系统和IO操作:Poco库提供了强大的文件系统和IO操作功能,包括文件读写、目录遍历、文件监控等,简化了文件和目录处理的过程。
- 单元测试和文档生成:Poco库内置了用于单元测试和文档生成的工具集,方便开发者进行代码测试、文档编写和生成。
3.安装
3.1.Windows 安装(推荐 vcpkg,最简单)
- 先安装 vcpkg(包管理器):
git clone https://github.com/microsoft/vcpkg && .\vcpkg\bootstrap-vcpkg.bat - 安装 Poco:
vcpkg install poco:x64-windows(x64 版本,默认静态库) - 项目配置(VS):右键项目→属性→VC++ 目录→包含目录 / 库目录,分别添加
vcpkg/installed/x64-windows/include和vcpkg/installed/x64-windows/lib
3.2.Linux 安装(Ubuntu/Debian)
- 方式 1:包管理器(快速):
sudo apt-get install libpoco-dev - 方式 2:源码编译(自定义版本):
- 下载源码:
wget https://github.com/pocoproject/poco/archive/refs/tags/poco-1.12.4-release.tar.gz - 解压编译:
tar -zxvf xxx.tar.gz && cd poco-xxx && mkdir build && cd build && cmake .. && make -j4 && sudo make install
- 下载源码:
4.Poco 核心模块详细使用
1.基础模块(Foundation):字符串 / 日志 / 文件
#include <Poco/String.h> // 字符串工具
#include <Poco/Logger.h> // 日志
#include <Poco/File.h> // 文件操作
#include <iostream>int main() {// 1. 字符串处理(忽略大小写比较、trim等)std::string str = " Hello Poco! ";std::cout << Poco::trim(str) << std::endl; // 输出 "Hello Poco!"std::cout << Poco::icompare(str, "hello poco!") << std::endl; // 0(相等)// 2. 日志(默认控制台输出)Poco::Logger& logger = Poco::Logger::get("MainLogger");logger.information("Poco 日志测试"); // 输出 [2024-xx-xx xx:xx:xx] [Information] MainLogger: Poco 日志测试// 3. 文件操作(创建文件夹、判断文件是否存在)Poco::File file("test_dir");if (!file.exists()) file.createDirectory(); // 创建文件夹std::cout << "文件夹是否存在:" << file.exists() << std::endl;return 0;
}
- 编译命令(Linux):
g++ main.cpp -o test -lPocoFoundation -lPocoUtil - 编译命令(Windows,VS 命令行):
cl main.cpp PocoFoundation.lib PocoUtil.lib
2.配置文件读取(Util 模块)
Poco 支持 INI 配置文件,适合项目参数管理:
#include <Poco/Util/PropertyFileConfiguration.h>
#include <iostream>int main() {try {// 读取 config.ini 文件Poco::AutoPtr<Poco::Util::PropertyFileConfiguration> pConfig = new Poco::Util::PropertyFileConfiguration("config.ini");// 获取配置项(key=value 格式)std::string ip = pConfig->getString("ftp.ip");int port = pConfig->getInt("ftp.port", 21); // 默认值 21std::cout << "FTP IP:" << ip << ",端口:" << port << std::endl;} catch (Poco::Exception& e) {std::cerr << "读取配置失败:" << e.displayText() << std::endl;}return 0;
}
3.FTP上传下载
下载代码:
#include <Poco/Net/FTPClientSession.h>
#include <Poco/Exception.h>
#include <fstream>
#include <iostream>int main() {const std::string FTP_IP = "ftp.example.com"; // FTP服务器IPconst int FTP_PORT = 21; // 端口(默认21)const std::string USER = "your_username"; // 用户名const std::string PWD = "your_password"; // 密码const std::string REMOTE_FILE = "remote/path/file.txt"; // 远程文件路径const std::string LOCAL_FILE = "local_file.txt"; // 本地保存路径try {// 1. 初始化会话+登录Poco::Net::FTPClientSession ftp(FTP_IP, FTP_PORT);ftp.login(USER, PWD);ftp.setPassiveMode(true); // 必开!解决防火墙端口阻塞问题// 2. 二进制模式打开本地文件,执行下载std::ofstream localFile(LOCAL_FILE, std::ios::binary);if (!localFile.is_open()) throw std::runtime_error("本地文件打开失败");ftp.retrieveFile(REMOTE_FILE, localFile); // 核心下载接口// 3. 清理资源localFile.close();ftp.close();std::cout << "下载成功!" << std::endl;}catch (Poco::Exception& e) {std::cerr << "FTP下载失败:" << e.displayText() << std::endl;return 1;}catch (std::exception& e) {std::cerr << "错误:" << e.what() << std::endl;return 1;}return 0;
}
上传仅替换下载的文件操作部分,其余代码一致:
// ... 前面连接、登录代码相同 ...// 2. 二进制模式读取本地文件,执行上传
std::ifstream localFile(LOCAL_FILE, std::ios::binary);
if (!localFile.is_open()) throw std::runtime_error("本地文件打开失败");
ftp.storeFile(REMOTE_FILE, localFile); // 核心上传接口// ... 后面关闭文件、会话代码相同 ...
支持断点续传的上传下载代码:
- 利用 FTP 的
REST命令(从指定字节偏移量开始传输)。 - Poco 通过
FTPClientSession::setFileOffset(offset)实现偏移量设置。
断点续传下载:
/*** 从FTP下载文件(支持断点续传)* @param ftp 已初始化的FTP会话* @param remotePath 远程文件路径(如 "remote/dir/largefile.zip")* @param localPath 本地保存路径(如 "local/dir/largefile.zip")*/
void downloadWithResume(FTPClientSession& ftp, const std::string& remotePath, const std::string& localPath) {try {// 1. 检查本地文件是否已存在,获取当前大小(作为续传起始点)File localFile(localPath);std::streamoff resumeOffset = 0;if (localFile.exists()) {resumeOffset = localFile.getSize();std::cout << "检测到部分文件,从 " << resumeOffset << " 字节开始续传..." << std::endl;}// 2. 设置FTP续传偏移量(关键步骤)ftp.setFileOffset(resumeOffset);// 3. 以"追加+二进制"模式打开本地文件,继续下载std::ofstream localStream(localPath, std::ios::binary | std::ios::app);if (!localStream.is_open()) {throw std::runtime_error("无法打开本地文件:" + localPath);}// 4. 执行下载(从偏移量开始)ftp.retrieveFile(remotePath, localStream);localStream.close();std::cout << "下载完成:" << localPath << std::endl;} catch (Exception& e) {std::cerr << "下载失败:" << e.displayText() << std::endl;throw; // 向上传递异常,方便外层处理}
}
断点续传上传:
/*** 向FTP上传文件(支持断点续传)* @param ftp 已初始化的FTP会话* @param localPath 本地文件路径(如 "local/dir/largefile.zip")* @param remotePath 远程保存路径(如 "remote/dir/largefile.zip")*/
void uploadWithResume(FTPClientSession& ftp, const std::string& localPath, const std::string& remotePath) {try {File localFile(localPath);if (!localFile.exists()) {throw std::runtime_error("本地文件不存在:" + localPath);}// 1. 获取本地文件总大小std::streamoff totalSize = localFile.getSize();// 2. 尝试获取远程文件当前大小(作为续传起始点)std::streamoff resumeOffset = 0;try {// 发送SIZE命令获取远程文件大小(部分服务器不支持,会抛异常)resumeOffset = ftp.size(remotePath);if (resumeOffset >= totalSize) {std::cout << "文件已完整上传,无需操作" << std::endl;return;}std::cout << "检测到部分上传,从 " << resumeOffset << " 字节开始续传..." << std::endl;} catch (Exception& e) {// 服务器不支持SIZE命令,从头开始上传std::cout << "服务器不支持续传检测,从头开始上传..." << std::endl;resumeOffset = 0;}// 3. 设置FTP续传偏移量ftp.setFileOffset(resumeOffset);// 4. 以"二进制"模式打开本地文件,并跳转到续传起始点std::ifstream localStream(localPath, std::ios::binary);if (!localStream.is_open()) {throw std::runtime_error("无法打开本地文件:" + localPath);}localStream.seekg(resumeOffset); // 移动读指针到偏移量// 5. 执行上传(从偏移量开始)ftp.storeFile(remotePath, localStream);localStream.close();std::cout << "上传完成:" << remotePath << std::endl;} catch (Exception& e) {std::cerr << "上传失败:" << e.displayText() << std::endl;throw;}
}
文件夹递归上传(含子目录和文件)
- 遍历本地文件夹的所有文件和子目录。
- 在 FTP 服务器上创建对应的目录结构(
createDirectory)。 - 递归上传所有文件(调用上面的
uploadWithResume支持断点续传)。
/*** 递归上传本地文件夹到FTP(含子目录)* @param ftp 已初始化的FTP会话* @param localDir 本地文件夹路径(如 "local/docs")* @param remoteParent 远程父目录(如 "remote/docs",上传后结构为 remote/docs/[localDir内容])*/
void uploadDirectory(FTPClientSession& ftp, const std::string& localDir, const std::string& remoteParent) {try {// 1. 检查本地文件夹是否存在if (!fs::is_directory(localDir)) {throw std::runtime_error("本地路径不是文件夹:" + localDir);}// 2. 拼接远程文件夹完整路径(localDir的最后一级目录名 + remoteParent)std::string remoteDir = remoteParent + "/" + fs::path(localDir).filename().string();// 确保远程目录存在(创建多级目录)ftp.createDirectory(remoteDir);std::cout << "创建远程目录:" << remoteDir << std::endl;// 3. 遍历本地文件夹中的所有条目for (const auto& entry : fs::directory_iterator(localDir)) {const std::string& entryPath = entry.path().string();if (entry.is_directory()) {// 递归上传子目录uploadDirectory(ftp, entryPath, remoteDir);} else if (entry.is_regular_file()) {// 上传文件(使用断点续传)std::string remoteFilePath = remoteDir + "/" + entry.path().filename().string();std::cout << "开始上传文件:" << entryPath << " -> " << remoteFilePath << std::endl;uploadWithResume(ftp, entryPath, remoteFilePath);}}std::cout << "文件夹上传完成:" << localDir << std::endl;} catch (Exception& e) {std::cerr << "文件夹上传失败:" << e.displayText() << std::endl;throw;} catch (std::exception& e) {std::cerr << "本地文件操作失败:" << e.what() << std::endl;throw;}
}
完整调用示例:
#include <Poco/Net/FTPClientSession.h>
#include <Poco/File.h>
#include <Poco/Path.h>
#include <fstream>
#include <iostream>
#include <filesystem> // C++17文件系统库(遍历文件夹用)namespace fs = std::filesystem;
using namespace Poco;
using namespace Poco::Net;// 初始化FTP会话(含被动模式)
FTPClientSession initFTPSession(const std::string& ip, int port, const std::string& user, const std::string& pwd) {FTPClientSession ftp(ip, port);ftp.login(user, pwd);ftp.setPassiveMode(true); // 强制开启被动模式,避免防火墙拦截return ftp;
}int main() {// FTP服务器配置(替换为实际信息)const std::string FTP_IP = "ftp.example.com";const int FTP_PORT = 21;const std::string USER = "your_username";const std::string PWD = "your_password";try {// 初始化FTP会话(含被动模式)FTPClientSession ftp = initFTPSession(FTP_IP, FTP_PORT, USER, PWD);// 示例1:断点续传下载downloadWithResume(ftp, "remote/bigfile.zip", "local/bigfile.zip");// 示例2:断点续传上传uploadWithResume(ftp, "local/report.pdf", "remote/report.pdf");// 示例3:递归上传文件夹uploadDirectory(ftp, "local/docs", "remote"); // 本地docs文件夹 -> 远程remote/docsftp.close();} catch (Exception& e) {std::cerr << "总错误:" << e.displayText() << std::endl;return 1;}return 0;
}
4.web服务示例
官方示例,实现了一个简单的多线程web服务器,为单个HTML页面提供服务,使用Foundation, Net和Util库,生成的网页在8080端口:
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Util/ServerApplication.h"
#include <iostream>using namespace Poco;
using namespace Poco::Net;
using namespace Poco::Util;class HelloRequestHandler: public HTTPRequestHandler
{void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response){Application& app = Application::instance();app.logger().information("Request from %s", request.clientAddress().toString());response.setChunkedTransferEncoding(true);response.setContentType("text/html");response.send()<< "<html>"<< "<head><title>Hello</title></head>"<< "<body><h1>Hello from the POCO Web Server</h1></body>"<< "</html>";}
};class HelloRequestHandlerFactory: public HTTPRequestHandlerFactory
{HTTPRequestHandler* createRequestHandler(const HTTPServerRequest&){return new HelloRequestHandler;}
};class WebServerApp: public ServerApplication
{void initialize(Application& self){loadConfiguration();ServerApplication::initialize(self);}int main(const std::vector<std::string>&){UInt16 port = static_cast<UInt16>(config().getUInt("port", 8080));HTTPServer srv(new HelloRequestHandlerFactory, port);srv.start();logger().information("HTTP Server started on port %hu.", port);waitForTerminationRequest();logger().information("Stopping HTTP Server...");srv.stop();return Application::EXIT_OK;}
};POCO_SERVER_MAIN(WebServerApp)
编译运行:
g++ -o main main.cpp -lPocoFoundation -lPocoNet -lPocoUtil && ./main

5.生成uuid示例
#include <iostream>
#include "Poco/UUIDGenerator.h"
#include "Poco/UUID.h"int main()
{// 使用默认的UUID生成器Poco::UUIDGenerator generator;// 生成一个随机UUIDPoco::UUID uuid1 = generator.createRandom();// 生成一个基于时间的UUIDPoco::UUID uuid2 = generator.createOne();// 输出UUIDstd::cout << "Random UUID: " << uuid1.toString() << std::endl;std::cout << "Time-based UUID: " << uuid2.toString() << std::endl;return 0;
}
5.与其他库的对比
- vs Boost:Boost 更侧重底层算法和数据结构(如
boost::asio、boost::container),Poco 更偏向 “应用层工具”(开箱即用的网络、日志等组件)。 - vs Qt:Qt 是完整的 GUI 框架,附带网络等功能;Poco 无 GUI,专注于后端非界面功能,更轻量。
