📄 cftpserver.cpp
字号:
#include "Comm.h"
#include "windows.h"
#define MAX_SIZ 256
#define BUFFSIZE 256
WComm w;
char F_Path[MAX_SIZ]; //服务器共享目录,程序运行中始终不变,
// 如果程序不指定,默认路径为程序运行的当前目录
char fb_path[MAX_SIZ]; //服务器当前路径,只有cd命令可以改变
void GetSharePath(char *SharePath);//配置服务器的共享路径
void DecodeCMD(char *buff); //解析客户端发送的命令,并分发给相应的处理函数
int IsExist(char *filename);//判断当前路径下是否存在filename文件
void Get(char *Cmd);
void Put(char *Cmd);
void Dir(char *Cmd);
void Cd(char *Cmd);
void main(int argc, char *argv[])
{
char buff[BUFFSIZE]="";
WIN32_FIND_DATAA FindFileData;
HANDLE hFind;
char SharePath[MAX_SIZ];
int Port;
char rec_ack[32] = "";
//程序参数判断
if(argc==1)
Port=10824;
else if(argc==2) //如果带1个参数
Port=(int)atoi(argv[1]);
else if(argc==3) //如果带2个参数
{
Port=(int)atoi(argv[1]);
hFind = FindFirstFile(argv[2], &FindFileData); //注意目录的形式后面要有*.*
if (hFind == INVALID_HANDLE_VALUE || FindFileData.dwFileAttributes!=FILE_ATTRIBUTE_DIRECTORY) //没有找到该文件
{
printf("服务器的共享路径配置错误,不存在这样的目录,请检查!");
exit(1);
}
else
{
strcat(F_Path,argv[2]); //设置服务器的共享路径
strcat(fb_path,argv[2]); //设置服务器当前路径
strcat(SharePath,argv[2]);
for(int i=strlen(SharePath);i>=0;i--)//去掉绝对路径
{
if(SharePath[i]=='\\')
{
for(int k=0;k+i+1<=strlen(SharePath);k++)
{
SharePath[k]=SharePath[i+k+1];
}
break;
}
}
}
}
else
{
printf("usage: %s [portnum] [SharePath]",argv[0]);
exit(2);
}
//获得服务器的共享路径
if(argc!=3)
{
GetModuleFileName(NULL,SharePath,MAX_SIZ);//获得程序所在路径
GetSharePath(SharePath);
}
//启动服务器
if(w.startServer(Port)==0)
{
printf("启动服务器失败!\n");
exit(2);
}
else
printf("服务器端已经启动,等待连接中...\n");
//进入永真循环
while(true)
{
w.waitForClient();
printf("客户端已经成功连接到了服务器...\n");
w.sendData(SharePath); //给客户端发送共享路径
while(true)
{
w.recvData(buff,BUFFSIZE);//接受客户段的命令
w.sendData("success!"); //发送响应信息
w.recvData(rec_ack,8);
DecodeCMD(buff);
if(strcmp(buff,"9")==0) //如果断开连接
{
w.closeConnection();
strcpy(fb_path,F_Path);
break;
}
strcpy(buff,"9");
}
printf("等待连接中...\n");
}
}
//获得服务器的共享目录
void GetSharePath(char *SharePath)
{
for(int i=MAX_SIZ-1;i>=0;i--)//去掉可执行文件名
{
if (SharePath[i]=='\\')
{
SharePath[i]='\0';
strcpy(F_Path,SharePath); //保存全路径
strcpy(fb_path,SharePath); //保存全路径副本
break;
}
}
for(int j=i;j>=0;j--)//去掉绝对路径
{
if(SharePath[j]=='\\')
{
for(int k=0;k+j+1<=i;k++)
{
SharePath[k]=SharePath[j+k+1];
}
break;
}
}
}
//解析命令
void DecodeCMD(char *buff)
{
int P_Num;//参数个数
char CmdName;
char temp[BUFFSIZE];
CmdName=buff[0];
P_Num=buff[1];
int i=3,j=0;//i:记录第一个参数长度处的下标
switch(CmdName)
{
case '0':
{
for(int pm=0;pm<P_Num;pm++)//pm控制提取参数的次数
{
int k=buff[i];//k记录每个文件名的长度
for(int jj=i+1;jj<=k+i;jj++)
{
temp[j++]=buff[jj];
}
i=jj;
temp[j]='\0';
j=0;
Get(temp);
}
break;
}
case '1':
{
Put(buff);
break;
}
case '2' :
{
//如果dir命令的参数为空
if(P_Num==0)
{
temp[0]='\0';
Dir(temp);
}
else
{
for(int pm=0;pm<P_Num;pm++)
{
int k=buff[i];
for(int jj=i+1;jj<=k+i;jj++)
{
temp[j++]=buff[jj];
}
i=jj;
temp[j]='\0';
j=0;
Dir(temp);
}
}
break;
}
case '3':
{
for(int pm=0;pm<P_Num;pm++)
{
int k=buff[i];
for(int jj=i+1;jj<=k+i;jj++)
{
temp[j++]=buff[jj];
}
i=jj;
temp[j]='\0';
j=0;
Cd(temp);
}
break;
}
case '4':
{
}
}
}
void Get(char *Cmd)
{
/////////////////////////////////////////////////////////////////////////
// //
// Zheng Feng //
// the server creates a file with this cmd, cmd is a name parameter //
// //
/////////////////////////////////////////////////////////////////////////
// test if it is an invalid name, such as "..\..\aa.txt"
char buffer[1025] = "";
bool invalid = false;
for(int i=0; i<strlen(Cmd); i++)
{
if(Cmd[i] == '\\')
{
invalid = true;
break;
}
}
if(invalid) // invalid file name
{
buffer[0] = 1;
w.blocksendData(buffer, 1);
strcpy(buffer, "0");
return;
}
else // a valid file name
{
buffer[0] = 0;
w.blocksendData(buffer, 1);
strcpy(buffer, "0");
}
w.recvData(buffer, 1);
strcpy(buffer, "0");
char currentPath[MAX_SIZ] = "";
strcpy(currentPath, F_Path);
strcat(currentPath, "\\");
strcat(currentPath, Cmd);
FILE *fr = NULL;
fr = fopen(currentPath, "rb");
// Zheng Feng
// test if it is a valid file name in the server disk
if(fr == NULL) // invalid file
{
strcpy(buffer, "111111"); // packet start flag
buffer[6] = 1; // packet type
buffer[7] = 1; // control type
buffer[8] = 2;
buffer[9] = 15; // in all length
strcpy(buffer+10, "111111"); // packet end flag
buffer[16] = '\0';
w.sendData(buffer);
strcpy(buffer, "0");
return;
}
else // valid file
{
strcpy(buffer, "111111"); // packet start flag
buffer[6] = 1; // packet type
buffer[7] = 1; // control type
buffer[8] = 1;
buffer[9] = 15; // in all length
strcpy(buffer+10, "111111"); // packet end flag
buffer[16] = '\0';
w.sendData(buffer);
strcpy(buffer, "0");
}
w.recvData(buffer, 1024);
strcpy(buffer, "0");
// Zheng Feng
// if valid, begin transfer
// first, send the file name
w.sendData(Cmd);
w.recvData(buffer, 1024);
if(buffer[0] == 1)
{
printf("client receive filename successfully.\n");
}
else
{
printf("client receive filename error.\n");
return;
}
strcpy(buffer, "0");
// second, get the file size
fseek(fr, 0L, SEEK_END);
long size = ftell(fr);
fseek(fr, 0L, SEEK_SET);
// third, send the file size
char filesize[32] = "";
_ltoa(size, filesize, 10);
w.sendData(filesize);
w.recvData(buffer, 1024);
if(buffer[0] == 1)
{
printf("client receive filesize successfully.\n");
}
else
{
printf("client receive filesize error.\n");
return;
}
strcpy(buffer, "0");
buffer[0] = 1;
w.sendData(buffer);
strcpy(buffer, "0");
///////////////////////////////////////////////////////////////////////////////
w.recvData(buffer, 32);
long size_already = atol(buffer);
strcpy(buffer, "0");
buffer[0] = 1;
w.sendData(buffer);
strcpy(buffer, "0");
if(size_already != 0)
{
fseek(fr, size_already, SEEK_SET);
size = size - size_already;
}
w.recvData(buffer, 1);
///////////////////////////////////////////////////////////////////////////////
char fileBuffer[1025] = "";
while(size > 0)
{
if(size >= 1024)
{
fread(fileBuffer, 1024, 1, fr);
w.blocksendData(fileBuffer,1024);
w.recvData(buffer, 1024);
strcpy(fileBuffer, "0");
strcpy(buffer, "0");
}
else
{
fread(fileBuffer, size, 1, fr);
w.blocksendData(fileBuffer,size);
w.recvData(buffer, 1024);
strcpy(fileBuffer, "0");
strcpy(buffer, "0");
}
size -= 1024;
}
fclose(fr);
printf("send %s OK\n", Cmd);
}
void Put(char *Cmd)
{
char buff[BUFFSIZE]="";
char rec[50] = "";
w.recvData(buff,BUFFSIZE);//接收客户端发送的文件是否可发送标识
if(strcmp(buff,"0")==0)//如果出现错误,直接返回
return;
w.sendData("OK");//告诉客户端,服务器已经准备好了接收数据
for(int i=0;i<Cmd[1];i++)//循环接收客户端发送的文件
{
w.fileReceive(fb_path);
printf("The file has been received successfully...\n");//打印文件发送完成
}
}
//dir命令处理函数
void Dir(char *Cmd)
{
char dirname[256]; //用来存储路径
int n,m,k;
int flag=0;
char rec_ack[32]=""; //接收客户端返回信息的缓冲区
HANDLE h; //一个句柄
WIN32_FIND_DATA f; //一个文件数据结构
char sendinf[1024]; //定义数据缓存
strcpy(sendinf,"0"); //初始化数据缓存
strcpy(dirname,fb_path);
n=strlen(Cmd); //如果参数为空,则人为的加入一个参数.
if(n==0)
{
Cmd[0]='.';
Cmd[1]='\0';
}
if(strcmp(Cmd,".")==0)//如果参数是.则把\*添加到当前路径的后面作为搜索路径
strcat(dirname,"\\*");
else if(strcmp(Cmd,"..")==0)//如果参数是..先判断是否越权
if(strcmp(F_Path,dirname)==0)//如果越权,给客户端返回一个错误提示信息'3'
{
w.sendData("3");
w.recvData(rec_ack,32);
return;
}
else//如果没有越权,当前路径向前退一级,并在其后加\*
{
for(int i=strlen(dirname)-1;i>=0;i--)
{
if(dirname[i]=='\\')
{
dirname[i]='\0';
break;
}
}
strcat(dirname,"\\*");
}
else//如果参数是其他的
{
flag=IsExist(Cmd);//先判断参数文件是否存在
if(flag==0)//如果不存在向客户端发送一个提示信息'0'
{
w.sendData("0");
w.recvData(rec_ack,32);
printf("DIR 命令执行失败,参数错误!\n");
return;
}
else if(flag==2)//如果存在但不是一个文件夹,则向客户端发送一个提示信息'2'
{
w.sendData("2");
w.recvData(rec_ack,32);
printf("DIR 命令执行失败,参数错误!\n");
return;
}
else//如果找到用户访问的文件夹,则在当前搜索路径末尾加\Cmd\*
{
strcat(dirname,"\\");
strcat(dirname,Cmd);
strcat(dirname,"\\*");
}
}
w.sendData("1");//向客户端发送文件夹存在信息
w.recvData(rec_ack,32);
//开始获取文件目录信息
k=strlen(sendinf);
h=FindFirstFile(dirname,&f);
if(h)
{
m=strlen(f.cFileName);
sendinf[k++]=m;
if(f.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)//如果是文件夹
sendinf[k++]=1;
else
sendinf[k++]=0;
sendinf[k]='\0';
strcat(sendinf,f.cFileName);
k=strlen(sendinf);
}
while(h)
{
if(FindNextFile(h,&f))//如果找到下一个文件
{
m=strlen(f.cFileName);
if(k+m+1<1023)//如果当前祯有足够的长度来编码当前搜索的文件
{
sendinf[k++]=m;
if(f.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)//如果是文件夹
sendinf[k++]='d';//将标示位置为'd'
else
sendinf[k++]='f';//将标示位置为'f'
sendinf[k]='\0';
strcat(sendinf,f.cFileName);
k=strlen(sendinf);
}
else//如果没有足够的位置
{
sendinf[0]='1';//改变当前祯的后续标示位为'1',来标示还将发送后续数据
w.sendData(sendinf); //发送数据
w.recvData(rec_ack,32); //接受客户端的反馈信息!
strcpy(sendinf,"0");//重新初始化数据缓存
k=strlen(sendinf); //从新计算当前数据缓存的已用字节数
}
}
else//如果没有找到下一个文件
{
if( GetLastError() == ERROR_NO_MORE_FILES )//如果错误标识是搜索结束
break;//结束循环
}
}
FindClose(h);//释放句柄
w.sendData(sendinf);//发送数据
w.recvData(rec_ack,32);//接收客户端的返回信息
printf("DIR 命令执行成功!\n");
}
void Cd(char *Cmd)
{
//cout<<"**************************Cd命令:"<<endl;
//WIN32_FIND_DATAA FindFileData;
//HANDLE hFind;
char temp[BUFFSIZE];
int P_len=0;
int p_num,i=0; //参数个数
p_num=Cmd[1];
P_len=Cmd[3]; //参数长度
strcpy(temp,fb_path);
if(Cmd[0]=='.'&&Cmd[1]!='.')//CD.的情况///Cmd[0]=='.'&&Cmd[1]=='\0'
{
}
else if(Cmd[0]=='.'&&Cmd[1]=='.')//cd..的情况//////////////////////////////////
{
if(Cmd[2]=='\0')
{
if(strcmp(F_Path,fb_path)!=0)
{
int len=strlen(fb_path);
while(fb_path[len]!='\\')
len--;
fb_path[len]='\0';
}
printf("当前路径为:%s\n",fb_path);
}
}
else //cd后跟一个文件夹的情况
{
int exist=IsExist(Cmd);
if(exist==1)
{
strcat(fb_path,"\\");
strcat(fb_path,Cmd);
printf("当前路径为:%s\n",fb_path);
w.sendData("1");
}
else
w.sendData("0");
}
}
int IsExist(char *filename)
{
char dirname[256];
int n;
strcpy(dirname,fb_path);
n=strlen(dirname);
dirname[n++]='\\';
dirname[n++]='*';
dirname[n]='\0';
HANDLE h;
WIN32_FIND_DATA f;
h=FindFirstFile(dirname,&f);
if(strcmp(filename,f.cFileName)==0)//如果在当前目录下找到同名文件
if(f.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)//如果是文件夹
return(1);
else
return(2);
while(h)
{
if(FindNextFile(h,&f))
{
if(strcmp(filename,f.cFileName)==0)
if(f.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)//如果是文件夹
return(1);
else
return(2);
}
else
{
if( GetLastError() == ERROR_NO_MORE_FILES )
break;
}
}
FindClose(h);
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -