⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cftpserver.cpp

📁 一个用来模拟FTP工作流程的小程序
💻 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 + -