📄 95-116.txt
字号:
//SFTPLinuxer.cpp
#include <studio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "define.h"
extern int errno;
//关闭文件描述符或socket,打印错误信息,并退出程序:
void do_error (int fd,char *msg)
{
//close the valid file descriptor
if(fd>0)
close(fd);
//print out the error message
perror (msg);
exit(1);
}
//从给定的套接字描述符fd中读取完整的命令报文:
void do_read_cmd(int fd,CmdPacket *ptr)
{
int count=0;
int size =sizeof(CmdPacket);
while(count<size)
{
int flag=read(fd,(char*)ptr+count,size-count);
if(flag==-1)
do_error(fd,"read command error");
count+=flag;
}
}
//发送由参数ptr指向的回复报文:
void do_writer_rspns(int fd,RspnsPacket *ptr)
{
int size=sizeof(RspnsPacket);
int flag=write(fd,(char*)ptr,size);
int (flag==-1)
do_error(fd,"write response error");
}
//从描述fd读取大小为n的数据至缓冲区buf:
int do_read_data(int fd,char *buf,int n)
{
int flag=read(fd,buf,n);
if(flag==-1)
do_error(fd,"read data error");
return flag;
}
//向描述符fd发送缓冲区buf中的内容,大小为n:
int do_write_data(int fd,char *buf,int n)
{
int flag=write(fd,buf,n);
int (flag==-1)
do_error(fd,"write data error");
return flag;
}
//创建与客户端的数据连接,参数their_addr指明了客户端数据连接侦听的IP地址:
int connect_data_socket(struct sockaddr_in *their_addr)
{
int data_sockfd;
//create an endpoint for data communication
if(data_sockfd=socket(AF_INET,SOCK_STREAM,0)==-1)
do_error(data_sockfd,"socket error in connect_data_socket");
their_addr->sin_port=htons(DATA_PORT);
//initiate a connection on the socket
if(connect(data_sockfd,(struct sockaddr *)their_addr,sizeof(struct sockaddr))==-1)
do_error(data_sockfd,"connect error in connect_data_socket");
return data_sockfd;
}
//处理list命令:
void list(int sockfd,char *data_buf,struct sockaddr_in *their_addr)
{
char mode[11];
char path[80];
char tmp[80];
DIR *dir;
struct dirent *ptr;
struct stat info;
int data_sockfd=connect_data_socket(their_addr);
bzero(data_buf,DATA_BUFSIZE);
getcwd(path,80);
dir=opendir(path);
while((ptr=readdir(dir)!=NULL)
{
memset(mode,'-',10);
//get the full path including filename
strcpy(tmp,path);
if(tmp[strlen(tmp)-1]!='/')
strcat(tmp,"/");
strcat(tmp,pte->d_name);
//get the access control list
if(stat(tmp,&info)==-1)
do_error(sockfd,"stst error");
if(((info.st_mode&S_IFMT)==S_IFDIR)
mode[0]='d';
if(info.st_mode&S_IRUSR)
mode[1]='r';
if(info.st_mode&S_IWUSR)
mode[2]='w';
if(info.st_mode&S_IXUSR)
mode[3]='x';
if(info.st_mode&S_IRGRP)
mode[4]='r';
if(info.st_mode&S_IWGRP)
mode[5]='w';
if(info.st_mode&S_IXGRP)
mode[6]='x';
if(info.st_mode&S_IROTH)
mode[7]='r';
if(info.st_mode&S_IWOTH)
mode[8]='w';
if(info.st_mode&S_IXOTH)
mode[9]='x';
mode[10]='\0';
//output to the data_buf
strcat(data_buf,mode);
strcat(data_buf,"\t");
sprintf(tmp,"%-16s",ptr->d_name);
strcat(data_buf,tmp);
strcat(data_buf,"\t");
sprintf(tmp,"%ld",info.st_size);
strcat(data_buf,tmp);
strcat(data_buf,"\t");
strcat(data_buf,ctime(&info.st_mtime));
if(strlen(data_buf)>DATA_BUFSIZE-120)
{
do_write_data(data_sockfd,data_buf,strlen(data_buf));
bzero(data_buf,DATA_BUFSIZE);
}
}
closedir(dir);
do_write_data(data_sockfd,data_buf,strlen(data_buf)+1);
close(data_sockfd);
printf("%s:ls\n",inet_inet(their_addr->sin_addr));
}
//处理pwd命令:
void pwd(int sockfd,struct sockaddr_in *their_addr)
{
RspnsPacket rspns_packet;
rspns_packet.rspnsid=OK;
getcwd(rspns_packet.text,256);
strcat(rspns_packet.text,"\n");
do_write_rspns(sockfd,&rspns_packet);
printf("%s:pwd\n",inet_ntoa(their_addr->sin_addr));
}
//处理cd命令:
void cd(int sockfd,char *newpath,struct sockaddr_in *their_addr)
{
int flag;
RspnsPacket rspns_packet;
if((flag=chdir(newpath))==-1)
{
rspns_packet.rspnsid=ERR;
strcpy(rspns_packet.text,"invalid path\n");
}
else
{
rspns_packet.rspnsid=OK;
getcwd(rspns_packet.text,256);
printf("%s:cd%s\n",inet_ntoa(their_addr->sin_addr),newpath);
}
do_writer_rspns(sockfd,&rspns_packet);
}
//客户端下载文件:
voidget_file(int sockfd,char *data_buf,char*filename,struct sockaddr_in*their_addr)
{
RspnsPacket rspns_packet;
int fd;
int data_sockfd;
int count;
//检测是否目录
DIR *dir=opendir(filename);
if(dir!=NULL)
{
rspns_packet.rspnsid=ERR;
sprintf(rspns_packet.text,"%s is a Directory. Please get a File!\n",filename);
do_writr_rspns(sockfd,&rspns_packet);
closedir(dir);
return;
}
//打开文件用于读
fd=open(filename,O_RDONLY);
if(fd==-1)
{
rspns_packet.rspnsid=ERR;
if(errno==ENOENT)
sprintf(rspns_packet.text,"%s is an invalid path.\n".filename);
else
sprintf(rspns_packet.text,"Can't open file %s. Please try again!\n",filename);
do_write_rspns(sockfd,&rspns_packet);//发送回复报文
ruturn;
}
else
{
rspns_packet.rspnsid=OK;
do_write_rspns(sockfd,&rspns_packet);//发送回复报文
}
//建立与客户端的数据连接:
data_sockfd=connect_data_socket(their_addr);
//从文件中读取数据并发送至网络:
while((count=do_read_data(fd,data_buf,DATA_BUFSIZE))!=0)\
do_write_data(data_sockfd,data_buf,count);
close(data_sockfd);
close(fd);
printf("%s:get file %s\n",inet_ntoa(their_addr->sin_addr),filename);
}
//客户端上传文件:
voidput_file(int sockfd,char*data_buf,char*filename,struct sockaddr_in*their_addr)
{
RspnPacket rspns_packet;
int fd;
int data_sockfd;
int count;
//打开或创建文件用于写
fd=open(filename,O_WRONLY|O_CREAT|O_EXCL);
if(fd==-1)
{
rspns_packet.rspnsid=ERR;
if(error==EEXIST)
sprintf(rspns_packet.text,"%s allready exists.Please use another filename!\n",filename);
else
sprintf(rspns_packet.text,"Can't create file %s.Please try again!\n",filename);
do_write_rspns(sockfd,&rspns_packet);
return;
}
else
{
rspns_packet.rspnsid=OK;
do_write_rspns(sockfd,&rspns_packet);
}
//建立与客户端的数据并写入文件:
while((count=do_read_data(data_sockfd,data_buf,DATA_BUFSIZE))!=0)
do_write_data(fd,data_buf,count);
close(data_sockfd);
close(fd);
printf("%s: put file %s\n",inet_ntoa(their_addr->sin_addr),filename);
}
//本函数用于处理一对服务器与客户端之间的交互:
void run(int sockfd,struct sockaddr_in*their_addr)
{
CmdPacket cmd_packet;
RspnsPacket rspns_packet;
char data buf[DATA_BUFSIZE];
构建欢迎信息发送给客户端:
rspns_packet.rspnsid=OK;
strcpy(rspns_packet.text,"Welcome to Simple FTP Server!\n");
strcat(rspns_packet.text,"Have a good time!\n");
strcat(rspns_packet.text,"Operations:\n");
strcat(rspns_packet.text,"Is/pwd/cdpath/get filename/put filename/quit\n");
do_write_rspns(sockfd,&rspns_packet);
//主循环:读取命令报文,分派处理命令:
while(l)
{
do_read_cmd(sockfd,&cmd_packet);
switch(cmd_packet.cmdid)
{
case LS:
list(sockfd,data_buf,their_addr);break;
case PWD:
pwd(sockfd,their_addr);break;
case CD:
cd(sockfd,cmd_packet.param,their_addr);break;
case GET:
get_file(sockfd,data_buf,cmd_packet.param,their_addr);break;
case QUIT:
rspns_packet.rspnsid=OK;
strcpy(rspns_packet.text,"Bye_bye!\n";
do_write_rspns(sockfd,&rspns_packet);
printf("%s:quit\n",inet_ntoa(their_addr_>sin_addr));
break;
default:
rspns_packet.rspnsid=ERR;
strcpy(rspns_packet.text,"Invalid Command!\n");
do_write_rspns(sockfd,&rspns_packet);
break;
}
if(cmd_packet.cmdid==QUIT)
break;
}
close(sockfd);
}
//服务器端的主程序:
int main()
{
int sockfd,cmd_sockfd;struct sockaddr_in my_addr,their_addr;
int sin_size,on=1;
pid_t pid;
//首先为控制连接创建一个侦听socket:
if((sockfd=socket(AF_INET,SOCK_STREMA,0))==-1)
do_error(sockfd,"socket error");
if((setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(char*)&on,sizeof(on))==-1)
do_error(sockfd,"setsockopt error in create_data_socket");
my_addr.sin_family=AF_INET;
my_addr.sin_port_htons(CMD_PORT);
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&(my_addr.sin_zero),8);
// 绑定
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))=-1)
do_error(sockfd,"bind error");
//侦听控制连接请求:
if(listen(sockfd,BACKLOG)==-1)
do_error(sockfd,"listen error");
printf("Simple FTP Serve Version 1.0 is running!\n");
printf(tips:Ctrl+c to quit for while(1)loop\n");
//循环等待控制连接请求,接受连接请求和生成子进程
while(l)
{
sin_size=sizeof(struct sockaddr_in);
//准备接受连接请求:
if((cmd_sockfd=accept(sockfd,(struct sockaddr*)&their_addr,(socklen_t*)&sin_size))=-1)
{
if(errno!=EINTR)
do_error(sockfd,"accept error");
//If the system call was interrupted by a singnal that was
//caugth before a valid connection arrived,then coutinue.
countinue;
}
//创建一个子进程来处理相应客户端的工作:
pid=fork();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -