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可算是一个简 ... 
随机推荐
- 聚合查询 分组查询 F与Q查询 添加新字段
			目录 聚合查询 aggregate 聚合函数 起别名 分组查询 annotate 注释函数 起别名 分组查询报错 分组查询练习 总结 添加新字段 F与Q查询 F查询 字符串拼接 concat方法 Q查 ... 
- 【3rd_Party】使用QuaZip进行压缩和解压缩文件
			QuaZIP使用记录 官方文档 一.QuaZIP是什么 QuaZIP is a simple C++ wrapper over Gilles Vollant's ZIP/UNZIP package t ... 
- #2035:人见人爱A^B
			实现代码 #include<iostream> using namespace std; int main() { int n, m, t; while (cin >> n & ... 
- 打造绿色城市,数字孪生天然气站 3D 可视化
			前言 天然气作为常见的燃料,与我们的生活息息相关,而对于这种燃料的存储与传输,对于天然气供应站有着严格的要求.燃气企业一般都会将点供站设计为无人值守站,而往往在运营管理过程中,对点供站的安全管理尤为重 ... 
- 五、java操作redis
			系列导航 一.redis单例安装(linux) 二.redis主从环境搭建 三.redis集群搭建 四.redis增加密码验证 五.java操作redis --demo主方法 package com. ... 
- fetch与axios
- [转帖]Linux命令之——rsync
			文章目录 1 rsync是干什么用的 2 rsync和scp有什么区别 3 rsync简单用法介绍 rsync四种工作方式 1. 本地文件系统上实现同步 2. 本地主机使用远程shell和远程主机通信 ... 
- [转帖]学习如何编写 Shell 脚本(进阶篇)
			https://juejin.cn/post/6935365727205457928 前言 在<学习如何编写 Shell 脚本(基础篇)>一文中已经讲解了 Shell 脚本编程的基础知识, ... 
- [转帖]TiDB 5.1 Write Stalls 应急文档
			https://tidb.net/blog/ac7174dd#4.%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%87%BA%E7%8E%B0%E4%BA%86%20w ... 
- [转帖]jmeter之使用csv文件传递参数-05篇
			csv文件格式,第一列为手机号,第二列为密码 1.右键添加一个配置元件---csv数据文件设置 2.设置csv数据提取路径 3.引用数据 4.设置线程循环运行两次,然后发送请求 看到结果就执行了两次, ... 
