三、服务器功能实现与关键函数

1.头文件信息

头文件ftp.h包含系统信息:

#ifndef __FTP_H_

#define __FTP_H_

#define COMMAND_NUM 7

#define FILE_TRANS_MODE_ASIC 0

#define FILE_TRANS_MODE_BIN 1

char clientCommand[COMMAND_NUM][20]={{"pwd"}, {"quit"},{'?'},{"ls"},{"cd"}, {"get"},{"put"}};

char serverInfo220[]="220 myFTP Server ready.../r/n";

char serverInfo230[]="230 User logged in, proceed./r/n";

char serverInfo331[]="331 User name okay, need password./r/n";

char serverInfo221[]="221 Goodbye!/r/n";

char serverInfo150[]="150 File status okay; about to open data connection./r/n";

char serverInfo226[]="226 Closing data connection./r/n";

char serverInfo200[]="200 Command okay./r/n";

char serverInfo215[]="215 Unix Type FC5./r/n";

char serverInfo213[]="213 File status./r/n";

char serverInfo211[]="211 System status, or system help reply./r/n";

char serverInfo350[]="350 Requested file action pending further information./r/n";

char serverInfo530[]="530 Not logged in./r/n";

char serverInfo531[]="531 Not root client. Anonymous client./r/n";

char serverInfo[]="202 Command not implemented, superfluous at this site./r/n";

#endif

2.处理客户端命令

定义权限用户名及密码:

const char       default_user[] = "root";

const char       default_pass[] = "1234";

定义匿名用户及密码:

const char      anony_user[]="anonymous";

const char      anony_pass[]="anonymous";

函数*Handle_Client_Request(void* arg)处理客户需求,从客户端连接成功开始到结束服务。其中调用do_client_work(info->client_sock,info->client)函数与客户端交互。

void *Handle_Client_Request(void* arg)

{

struct ARG*info;

info=(struct ARG*)arg;

printf("You got a connection from %s/n",inet_ntoa(info->client.sin_addr));

do_client_work(info->client_sock,info->client);

close(info->client_sock);

pthread_exit(NULL);

}

函数do_client_work(int client_sock,struct sockaddr_in client)处理FTP各种命令。

void do_client_work(int client_sock,struct sockaddr_in client)

{

int login_flag;

login_flag=login(client_sock);

while(recv_client_info(client_sock)&&login_flag==1)//缺省用户操作响应

{

if((strncmp("quit", client_Control_Info, 4) == 0)||(strncmp("QUIT", client_Control_Info, 4) == 0))

{

send_client_info(client_sock, serverInfo221, strlen(serverInfo221));

break;

}

else if((strncmp("close",client_Control_Info,5) == 0)||(strncmp("CLOSE",client_Control_Info,5) == 0))

{

printf("Client Quit!/n");

shutdown(client_sock,SHUT_WR);

//关闭连接服务器,只关闭写操作。此时仍可进行客户端相关操作。

}

else if(strncmp("pwd", client_Control_Info, 3) == 0||(strncmp("PWD", client_Control_Info, 3) == 0))

{

char       pwd_info[MSG_INFO];

char       tmp_dir[DIR_INFO];

snprintf(pwd_info, MSG_INFO, "257 /"%s/" is current location./r/n", getcwd(tmp_dir, DIR_INFO));

send_client_info(client_sock, pwd_info, strlen(pwd_info));

}

else if(strncmp("cwd", client_Control_Info, 3) == 0||(strncmp("CWD", client_Control_Info, 3) == 0))

{

handle_cwd(client_sock);

}

else if(strncmp("mkd", client_Control_Info, 3) == 0||(strncmp("MKD", client_Control_Info, 3) == 0))

{

handle_mkd(client_sock);

}

else if(strncmp("rmd", client_Control_Info, 3) == 0||(strncmp("RMD", client_Control_Info, 3) == 0))

{

handle_rmd(client_sock);

}

else if(strncmp("dele", client_Control_Info, 4) == 0||(strncmp("DELE", client_Control_Info, 4) == 0))

{

handle_del(client_sock);

}

else if(strncmp("pasv", client_Control_Info, 4) == 0||(strncmp("PASV", client_Control_Info, 4) == 0))

{

handle_pasv(client_sock,client);

}

else if(strncmp("list", client_Control_Info, 4) == 0||(strncmp("LIST", client_Control_Info, 4) == 0))

{

handle_list(client_sock);

send_client_info(client_sock,serverInfo226, strlen(serverInfo226));

}

else if(strncmp("type", client_Control_Info, 4) == 0||(strncmp("TYPE", client_Control_Info, 4) == 0))

{

if(strncmp("type I", client_Control_Info, 6) == 0||(strncmp("TYPE I", client_Control_Info, 6) == 0))

translate_data_mode=FILE_TRANS_MODE_BIN;

send_client_info(client_sock, serverInfo200, strlen(serverInfo200));

}

else if(strncmp("retr", client_Control_Info, 4) == 0||(strncmp("RETR", client_Control_Info, 4) == 0))

{

handle_file(client_sock);

send_client_info(client_sock,serverInfo226, strlen(serverInfo226));

}

else if(strncmp("stor", client_Control_Info, 4) == 0||(strncmp("STOR", client_Control_Info, 4) == 0))

{

handle_file(client_sock);

send_client_info(client_sock,serverInfo226, strlen(serverInfo226));

}

else if(strncmp("syst", client_Control_Info, 4) == 0||(strncmp("SYST", client_Control_Info, 4) == 0))

{

send_client_info(client_sock, serverInfo215, strlen(serverInfo215));

}

else if(strncmp("size", client_Control_Info, 4) == 0||(strncmp("SIZE", client_Control_Info, 4) == 0))

{

send_client_info(client_sock, serverInfo213, strlen(serverInfo213));

}

else if(strncmp("feat", client_Control_Info, 4) == 0||(strncmp("FEAT", client_Control_Info, 4) == 0))

{

send_client_info(client_sock, serverInfo211, strlen(serverInfo211));

}

else if(strncmp("rest", client_Control_Info, 4) == 0||(strncmp("REST", client_Control_Info, 4) == 0))

{

send_client_info(client_sock, serverInfo350, strlen(serverInfo350));

}

else

{

send_client_info(client_sock, serverInfo, strlen(serverInfo));

}

}

while(recv_client_info(client_sock)&&(login_flag == 2))//匿名用户操作响应

{

//省略代码

}

}

函数int login(int client_sock)为登陆函数。处理客户端登录请求,与已定义的权限用户密码进行匹配,成功则为ROOT用户,失败则匹配匿名用户,匿名用户只能进行简单服务。

if(strncmp(format_client_Info, default_user, 4) == 0)

{

flag=1;

}

if(strncmp(format_client_Info, anony_user, 9) == 0)

{

flag=2;

}

函数void handle_cwd(int client_sock)处理转换目录功能。

关键代码:

if (chdir(client_dir) >= 0)

{

snprintf(cwd_info, MSG_INFO, "257 /"%s/" is current location./r/n", getcwd(tmp_dir, DIR_INFO));

send_client_info(client_sock, cwd_info, strlen(cwd_info));

}

else

{

snprintf(cwd_info, MSG_INFO, "550 %s :%s/r/n",client_dir,strerror(errno));

perror("chdir():");

send_client_info(client_sock, cwd_info, strlen(cwd_info));

}

上述代码表示当转换目录存在则把当前目录更改为转换目录,否则报错。

创建目录与删除目录关键代码与之类似。

函数void handle_mkd(int client_sock)处理创建目录功能。

关键代码:

if (mkdir(client_dir) >= 0)

{

printf(" /"%s/" is created successfully./r/n", client_dir);

send_client_info(client_sock, mkd_info, strlen(mkd_info));

}

else

{

snprintf(mkd_info, MSG_INFO, "550 %s :%s/r/n",client_dir,strerror(errno));

perror("mkdir():");

send_client_info(client_sock, mkd_info, strlen(mkd_info));

}

上述代码表示创建client_dir目录,成功输出消息,否则报错。

 

函数void handle_rmd(int client_sock)处理删除目录功能。

关键代码:

if (rmdir(client_dir) >= 0)

{

printf(" /"%s/" is deleted successfully./r/n", client_dir);

send_client_info(client_sock, rmd_info, strlen(rmd_info));

}

else

{

snprintf(rmd_info, MSG_INFO, "550 %s :%s/r/n",client_dir,strerror(errno));

perror("rmdir():");

send_client_info(client_sock, rmd_info, strlen(rmd_info));

}

上述代码表示删除client_dir目录,成功输出消息,否则报错。

 

函数handle_list(int client_sock)处理list命令。

FILE *pipe_fp;//建立管道以传输数据

char t_dir[DIR_INFO];

char list_cmd_info[DIR_INFO];

snprintf(list_cmd_info, DIR_INFO, "ls -l %s", getcwd(t_dir, DIR_INFO));//得到当前目录

if ((pipe_fp = popen(list_cmd_info, "r")) == NULL)//打开管道

{

printf("pipe open error in cmd_list/n");

return ;

}

printf("pipe open successfully!, cmd is %s/n", list_cmd_info);

char t_char;

while ((t_char = fgetc(pipe_fp)) != EOF)

{

printf("%c", t_char);

write(t_data_sock, &t_char, 1);

}//得到当前目录文件列表

pclose(pipe_fp);//关闭管道

printf("close pipe successfully!/n");

close(t_data_sock);

printf("%s close data successfully!/n",serverInfo226);

close(ftp_data_sock);

函数struct sockaddr_in create_date_sock()创建数据sock

struct sockaddr_in create_date_sock()

{

int t_client_sock;

struct sockaddr_in t_data_addr;

t_client_sock = socket(AF_INET, SOCK_STREAM, 0);//创建客户数据SOCK

if (t_client_sock < 0)

{

printf("create data socket error!/n");

return;

}

srand((int)time(0));

int a=rand()%1000+1025;

bzero(&t_data_addr, sizeof(t_data_addr));

t_data_addr.sin_family = AF_INET;

t_data_addr.sin_addr.s_addr = htonl(INADDR_ANY);

t_data_addr.sin_port = htons(a);

if (bind(t_client_sock, (struct sockaddr*)&t_data_addr, sizeof(struct sockaddr)) < 0)

{

printf("bind error in create data socket:%s/n",strerror(errno));

return;

}

listen(t_client_sock, LISTEN_QENU);

ftp_data_sock=t_client_sock;

return t_data_addr;

}

3.处理文件类命令

函数void handle_file(int client_sock)处理文件功能。把上传下载功能集成在一个函数中实现。

关键代码:

FILE* fp;//建立管道处理文件信息

int file_fd;

int n;

char t_dir[DIR_INFO];

char file_info[DIR_INFO];

snprintf(file_info, DIR_INFO, "%s/%s", getcwd(t_dir, DIR_INFO),format_client_Info);

//获得文件信息

if(strncmp(getcwd(t_dir, DIR_INFO),format_client_Info,strlen(getcwd(t_dir, DIR_INFO))-1)==0)

fp = fopen(format_client_Info, file_mode); //打开文件

else

fp = fopen(file_info, file_mode);

if(strncmp("retr", client_Control_Info, 4) == 0||(strncmp("RETR", client_Control_Info, 4) == 0))

{

while ((n = read(cmd_sock, client_Data_Info, MAX_INFO)) > 0)

{//读写文件

if (write(t_data_sock, client_Data_Info, n) != n)

{

printf("retr transfer error/n");

return;

}

}

}

else

{

while ((n = read(t_data_sock, client_Data_Info, MAX_INFO)) > 0)

{

if (write(cmd_sock, client_Data_Info, n) != n)

{

printf("stor transfer error/n");

return;

}

}

}

fclose(fp);    //关闭传输管道

close(t_data_sock);  //关闭数据sock

close(ftp_data_sock);       //关闭FTPsock

函数void send_client_info(int client_sock,char* info,int length)发送客户端信息。

函数int recv_client_info(int client_sock)接收客户端信息。

void send_client_info(int client_sock,char* info,int length)

{

int len;

if((len = send(client_sock, info, length,0))<0)

{

perror("send info error ");

return;

}

}

int recv_client_info(int client_sock)

{

int num;

if((num=recv(client_sock,client_Control_Info,MAX_INFO,0))<0)

{

perror("receive info error ");

return;

}

client_Control_Info[num]='/0';

printf("Client %d Message:%s/n",pthread_self(),client_Control_Info);

if(strncmp("USER", client_Control_Info, 4) == 0||strncmp("user", client_Control_Info, 4) == 0)return 2;

return 1;

}

函数void handle_del(int client_sock)处理删除目录功能。

关键代码:

if (unlink(client_file) >= 0)

{

printf(" /"%s/" is deleted successfully./r/n", client_file);

send_client_info(client_sock, del_info, strlen(del_info));

}

else

{

snprintf(del_info, MSG_INFO, "550 %s :%s/r/n",client_file,strerror(errno));

perror("unlink():");

send_client_info(client_sock, del_info, strlen(del_info));

}

上述代码表示删除文件client_file,成功输出消息,否则报错

文件传输协议的服务器相关推荐

  1. [转]文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1

    转自:http://blog.csdn.net/soarheaven/archive/2008/12/08/3474152.aspx 最近项目需要对FTP服务器进行操作,现把实现总结如下: 打算分2篇 ...

  2. Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1...

    相关文章导航 Sql Server2005 Transact-SQL 新兵器学习总结之-总结 Flex,Fms3相关文章索引 FlexAir开源版-全球免费多人视频聊天室,免费网络远程多人视频会议系统 ...

  3. p2p服务器的协议,P2P文件传输协议之BitTorrent协议

    BitTorrent协议是支持网络当中数据的上下传输的一个P2P文件传输协议.那么基于这个协议的BT软件大家肯定更不会陌生.但是它却有着更为广泛的使用,尤其是在一些大型网络数据交换平台中,也常常会使用 ...

  4. 简单文件传输协议TFTP分析还原

    " 介绍TFTP协议及传输内容的还原." TFTP,全称为Trivial File Transfer Protocol,即简单文件传输协议,是一个用来在客户端与服务器之间进行简单文 ...

  5. 知名文件传输协议 SCP 被曝存在 35 年历史的安全漏洞

    基于 SSH 的文件传输协议 SCP(Secure Copy Protocol)被曝存在安全漏洞. 安全研究人员公布了 SCP 存在的多个漏洞,这些漏洞可以结合起来利用,分别为 CVE-2018-20 ...

  6. 互联网协议 — FTP 文件传输协议

    目录 文章目录 目录 FTP vsftpd 自动模式和被动模式 PORT 主动模式 PASV 被动模式 访问控制方式 部署配置 FTP Server Global config Anonymous U ...

  7. FTP,SFTP,FTPS三个文件传输协议的区别

    FTP,SFTP,FTPS三个文件传输协议的区别 文章目录: 简要说明 FTP(File Transfer Protocol):文件传送协议是 TCP/IP 协议组中的协议之一.FTP协议包括两个组成 ...

  8. 【计算机网络】应用层 : 总结 ( 网络应用模型 C/S P2P | 域名解析 DNS | 文件传输协议 FTP | 电子邮件 | 万维网 与 HTTP ) ★★★

    文章目录 一.网络应用模型 ★ 二.域名解析过程 ★ 三.FTP 文件传输协议 四.电子邮件★ 五.万维网 和 HTTP 协议★ 一.网络应用模型 ★ 网络应用模型 : ① 客户 / 服务器 模型 ( ...

  9. 浅析文件传输协议 (ftp) 的工作原理

    起初,FTP并不是应用于IP网络上的协议,而是ARPANEt网络中计算机间的文件传输协议, ARPANET是美国国防部组建的老网络,于1960-1980年使用.在那时, FTP的主要功能是在主机间高速 ...

最新文章

  1. 从抵触到力推,.Net Core 的成功让微软正视开源
  2. hdu4091(暴力)
  3. 2015/Province_C_C++_C/8/饮料换购
  4. python-第二块:time模块和datatime模块
  5. 解决升级 Office 2010 之后 Outlook 提示“无法打开 Microsoft Outlook”
  6. ieee754浮点数转换工具_关于JS浮点数运算不精确的原因和解决方案
  7. 以厘php框架 v10.6.8
  8. Python 2.7.X安装dpkt, sendpkt, pycap
  9. cartographer探秘之文章索引
  10. 注册测绘师成绩查询,2020注册测绘师成绩公布
  11. python3操作shp文件
  12. 21世纪的“影子王国”:GPT-3,又一场科技革命的来临
  13. 人工鱼群算法Matlab实现
  14. 简单聊聊电商系统的订单号生成规则
  15. 2016年全球半导体厂商TOP20排名
  16. Arduino /*传感器使用指南
  17. Python期末考试-中心点问题
  18. python爬虫爬取京东商品评价_python爬取京东商品信息及评论
  19. 一文了解循环神经网络
  20. 为何苹果电脑虚拟机如此受欢迎

热门文章

  1. 预告:揭秘7*24小时用数学解码交易的神秘玩家,量化交易者——TokenInsight对话首席...
  2. 通读c++ primer
  3. preg_replace() 正则替换所有符合条件的字符串
  4. 服务器是做什么用的?具体用途有哪些?
  5. FL Studio水果2023版本更新下载汉化教程
  6. win11怎么关闭自动更新系统
  7. 端午送粽子祝福微信小程序源码下载支持打赏模式带背景音乐
  8. iPad莫名其妙黑屏了,无法打开屏幕?
  9. 华为语音解锁设置_华为设置语音服务功能
  10. 重绘、重排区别及如何减少