远程目录列表的获取也是一种很常用的功能,通常在远程控制软件中都存在此类功能,实现此功能可以通过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;
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 *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; }
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 };
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;
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
目录下的所有文件信息,文件属性,以及文件大小,输出效果如下图所示;