19.11 Boost Asio 获取远程目录
远程目录列表的获取也是一种很常用的功能,通常在远程控制软件中都存在此类功能,实现此功能可以通过filesystem.hpp库中的directory_iterator迭代器来做,该迭代器用于遍历目录中的文件和子目录,它允许开发者轻松遍历目录层次结构并对遇到的文件和目录执行各种操作。
使用directory_iterator构造函数创建一个迭代器,该迭代器指向目录中的第一个条目。然后,我们使用一个范围for循环来遍历目录中的每个文件和目录,并使用pos->path().string()方法即可得到该目录下的文件路径。
当然,directory_iterator仅遍历目录的直接子文件夹。如果想遍历目录层次结构中的所有文件和目录,则需要改用recursive_directory_iterator来实现递归遍历,或者自行拼接路径完成遍历。
服务端代码实现如下,在代码中我们通过write_some发送需要获取远程目录字符串,接着通过调用一次read_some接收一次需要循环的次数,当收到客户端传来的目录列表数量后,则可以在循环内依次调用read_some函数读取数据,并格式化为CatalogData类型,并输出其变量中的数据。
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/asio.hpp>
// 定义结构体,将完整数据放入结构体中
typedef struct
{
char file_path[2048];
bool is_directory;
long file_size;
}CatalogData;
using namespace std;
using namespace boost;
using namespace boost::asio;
CatalogData ptr;
int main(int argc, char* argv[])
{
io_service io_service;
ip::tcp::acceptor acceptor(io_service, ip::tcp::endpoint(ip::tcp::v4(), 6666));
ip::tcp::socket socket(io_service);
acceptor.accept(socket);
boost::system::error_code error_code;
// 发送需要获取的目录
socket.write_some(boost::asio::buffer("d://lyshark"), error_code);
// 接收文件数量
char recv_count[1024] = { 0 };
size_t len = socket.read_some(boost::asio::buffer(recv_count), error_code);
std::cout << "接收到数量: " << recv_count << std::endl;
// 判断如果数量大于等于1则需要循环获取
int for_count = lexical_cast<int>(recv_count);
if (for_count >= 1)
{
// 循环接收目录
for (int x = 0; x < for_count; x++)
{
// 准备接收缓冲区,以及接收数据包
char recv_catalogdata[sizeof(CatalogData)] = { 0 };
socket.read_some(boost::asio::buffer(recv_catalogdata, sizeof(CatalogData)), error_code);
// 将收到的字节序转换为CatalogData结构体
CatalogData *data = (CatalogData *)recv_catalogdata;
std::cout << "文件路径: " << data->file_path
<< "是否为目录: " << data->is_directory
<< "文件大小: " << data->file_size
<< std::endl;
memset(recv_catalogdata, 0, sizeof(CatalogData));
}
}
std::system("pause");
return 0;
}
客户端代码实现如下,相对于服务端客户端的实现则变得复杂一些,在代码中首先通过read_some函数调用获取到服务器端传来的目录C://usr信息,接着直接调用GetFileState函数并以此获取到当前目录下的文件列表信息,并将此信息存储到send_buffer容器内存储,接着再次调用write_some发送此容器内有多少行数据,最后通过使用循环的方式依次write_some发送send_catalogdata文件列表,直到全部发送结束则退出程序。
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <boost/filesystem.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace boost::filesystem;
// 定义结构体,将完整数据放入结构体中
typedef struct
{
char file_path[2048];
bool is_directory;
long file_size;
}CatalogData;
// 利用流获取文件大小
long GetFileSize(std::string filename)
{
long ref_kb;
std::ifstream ptr(filename, std::ios::in | std::ios::binary);
if (ptr.is_open() == true)
{
ptr.seekg(0, std::ios::end); // 移动到末尾
ref_kb = ptr.tellg(); // 获取字节数
ptr.close();
return ref_kb;
}
return 0;
}
// 遍历文件函数,并将结果存入RefVect
void GetFilePath(const string& pathName, std::vector <std::string> &RefVect)
{
directory_iterator end;
for (directory_iterator pos(pathName); pos != end; ++pos)
{
RefVect.push_back(pos->path().string());
}
}
// 获取到当前目录详细信息,并依次取出数据
std::vector<CatalogData> GetFileState(const string& pathName)
{
std::vector < std::string > ref_file_path;
GetFilePath(pathName,ref_file_path);
// 循环获取目录属性
std::vector<CatalogData> ref_date;
for (int x = 0; x < ref_file_path.size(); x++)
{
CatalogData ptr;
// 判断如果是目录,则不计算文件大小
if (is_directory(ref_file_path[x]))
{
ptr.is_directory = true;
ptr.file_size = 0;
strcpy(ptr.file_path, ref_file_path[x].c_str());
}
// 如果是文件则计算大小
else
{
ptr.is_directory = false;
ptr.file_size = GetFileSize(ref_file_path[x]);
strcpy(ptr.file_path, ref_file_path[x].c_str());
}
// 依次放入容器
ref_date.push_back(ptr);
}
return ref_date;
}
CatalogData ptr;
int main(int argc, char *argv[])
{
io_service io_service;
ip::tcp::socket socket(io_service);
ip::tcp::endpoint ep(ip::address_v4::from_string("127.0.0.1"), 6666);
boost::system::error_code error_code;
socket.connect(ep, error_code);
// 接收需要获取的目录地址
char recv_buf[1024] = { 0 };
size_t len = socket.read_some(boost::asio::buffer(recv_buf), error_code);
std::cout << "服务端需要获取: " << recv_buf << std::endl;
// 判断目录是否存在,存在则执行遍历目录
if (filesystem::exists(recv_buf))
{
std::vector<CatalogData> send_buffer;
send_buffer = GetFileState(recv_buf);
// 判断如果获取到了目录,则发送目录个数
if (send_buffer.size() > 0)
{
// 发送目录总数
std::string send_count = lexical_cast<std::string>(send_buffer.size());
std::cout << "获取到的目录文件数量: " << send_count << std::endl;
socket.write_some(boost::asio::buffer(send_count), error_code);
}
// 开始循环发送目录
for (int x = 0; x < send_buffer.size(); x ++)
{
// 填充局部结构并发送
char send_catalogdata[sizeof(CatalogData)] = { 0 };
// 拷贝将send_buffer依次赋值到ptr指针上
strcpy(ptr.file_path, send_buffer[x].file_path);
ptr.is_directory = send_buffer[x].is_directory;
ptr.file_size = send_buffer[x].file_size;
// 将字节序拷贝到send_catalogdata中
memcpy(send_catalogdata, &ptr, sizeof(CatalogData));
// 开始发送字节序
socket.write_some(boost::asio::buffer(send_catalogdata), error_code);
memset(send_catalogdata, 0, sizeof(CatalogData));
}
}
std::system("pause");
return 0;
}
至此读者可自行编译上述代码,并以此先运行服务端程序,接着再运行客户端程序,此时即可获取到远程主机中d://lyshark目录下的所有文件信息,文件属性,以及文件大小,输出效果如下图所示;

19.11 Boost Asio 获取远程目录的更多相关文章
- fabric动态获取远程目录列表
#!/usr/bin/pythonfrom fabric.api import *env.user='root'env.hosts=['172.10.224.183','172.10.224.132' ...
- 编译boost asio http/server 方法
这段时间学习boost 的asio 编程,想编译asio自带的http/server的程序,无奈在网上根本找不到方法,只能自己摸索学习. 登陆boost asio 的example 目录,(我 boo ...
- boost::asio 连接管理11 如何关闭连接
在实际产品运行中,对连接管理有了更新的认识,这里分享一下. shared_ptr管理连接对象的生命周期 shared_ptr的引用计数器决定了连接对象的生命周期.这里我说的连接对象就是在我的前文:ht ...
- Boost.Asio c++ 网络编程翻译(11)
*_at方法 这些方法在一个流上面做随机存取操作.你来指定read和write操作从什么地方開始(offset): async_read_at(stream, offset, buffer [, co ...
- 艰难的 debug 经历,vscode 无法获取远程环境 ssh 报错,windows 11 ssh
背景介绍 要做系统结构实验,学校和华为云合作使用华为云的 aarch64 裸机,需要使用 ssh 远程开发,笔者为了追求良好的开发体验,决定使用 vscode 开发,实验环境配置过程中遇到了两个问题, ...
- Boost.Asio基本原理(CSDN也有Markdown了,好开森)
Boost.Asio基本原理 这一章涵盖了使用Boost.Asio时必须知道的一些事情.我们也将深入研究比同步编程更复杂.更有乐趣的异步编程. 网络API 这一部分包含了当使用Boost.Asio编写 ...
- boost::asio 的同、异步方式
转自:http://blog.csdn.net/zhuky/archive/2010/03/10/5364574.aspx Boost.Asio是一个跨平台的网络及底层IO的C++编程库,它使用现代C ...
- boost::asio译文
Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENS ...
- PHP下通过file_get_contents\curl的方法实现获取远程网页内容(别忘了还有PhpRPC)
[php]PHP中file_get_contents()与file_put_contents()函数细节详解 php函数file_get_contents(一) 案例: 早在2010年时候遇到过这样的 ...
- boost asio 异步实现tcp通讯
---恢复内容开始--- asioboost 目录(?)[-] 一前言 二实现思路 通讯包数据结构 连接对象 连接管理器 服务器端的实现 对象串行化 一.前言 boost asio可算是一个简 ...
随机推荐
- 手把手教你配置JupyterLab 环境
Python 代码编辑器怎么选?PyCharm.VS Code.Jupyter Notebook 都各有特色. 对于大型代码库,最好还是用传统的 IDE 比较靠谱,但是数据分析等需要可视化操作的场景下 ...
- 【django drf】 阶段练习
目录 需求 settings.py views.py urls.py serializers.py permissions.py page.py authenticate.py model.py 权限 ...
- Educational Codeforces Round 92 (Rated for Div. 2) A~C
原作者为 RioTian@cnblogs, 本作品采用 CC 4.0 BY 进行许可,转载请注明出处. 最近写学习了一下网络爬虫,但昨天晚上的CF让人感觉实力明显退步,又滚回来刷题了QAQ... 比赛 ...
- Goolge Kick Start Round A 2020 (A ~ D题题解)
比赛链接:kick start Round A 2020 A. Allocation 题目链接 题意 给出 \(N\) 栋房子的价格,第 \(i\) 栋房子的价格为 \(A_i\),你有 \(B\) ...
- KMP 复习笔记
KMP 学习(复习)笔记 KMP(Knuth-Morris-Pratt)是算法竞赛中常用的字符串匹配算法之一,它可以有效地利用失配信息来使得匹配全过程中不回溯,从而在线性时间内完成匹配. 本文已有前置 ...
- Redis 内存优化在 vivo 的探索与实践
作者:vivo 互联网服务器团队- Tang Wenjian 一. 背景 使用过 Redis 的同学应该都知道,它基于键值对(key-value)的内存数据库,所有数据存放在内存中,内存在 Redis ...
- java项目实践-jsp-filter-监听器-day19
目录 1. jsp 2. 过滤器 3. listener 监听器 1. jsp servle逻辑处理方便 html页面表现麻烦 jsp 页面表现方便 但是逻辑处理麻烦 JSP 是一种页面技术 JSP本 ...
- ClickHouse的Join算法
ClickHouse的Join算法 ClickHouse是一款开源的列式分析型数据库(OLAP),专为需要超低延迟分析查询大量数据的场景而生.为了实现分析应用可能达到的最佳性能,分析型数据库(OLAP ...
- FinalShell上传文件失败
1.问题 上传文件失败,如图所示,即使切换至root用户 2.解决方式 这里在建立SSH连接时,就必须使用root用户,而若使用普通用户,即使在其中切换至root用户,也无法上传. 所以重新建立一个r ...
- ECharts——快速入门
ECharts快速入门 引入 ECharts <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...