文件传输协议的服务器
三、服务器功能实现与关键函数
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,成功输出消息,否则报错
文件传输协议的服务器相关推荐
- [转]文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1
转自:http://blog.csdn.net/soarheaven/archive/2008/12/08/3474152.aspx 最近项目需要对FTP服务器进行操作,现把实现总结如下: 打算分2篇 ...
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1...
相关文章导航 Sql Server2005 Transact-SQL 新兵器学习总结之-总结 Flex,Fms3相关文章索引 FlexAir开源版-全球免费多人视频聊天室,免费网络远程多人视频会议系统 ...
- p2p服务器的协议,P2P文件传输协议之BitTorrent协议
BitTorrent协议是支持网络当中数据的上下传输的一个P2P文件传输协议.那么基于这个协议的BT软件大家肯定更不会陌生.但是它却有着更为广泛的使用,尤其是在一些大型网络数据交换平台中,也常常会使用 ...
- 简单文件传输协议TFTP分析还原
" 介绍TFTP协议及传输内容的还原." TFTP,全称为Trivial File Transfer Protocol,即简单文件传输协议,是一个用来在客户端与服务器之间进行简单文 ...
- 知名文件传输协议 SCP 被曝存在 35 年历史的安全漏洞
基于 SSH 的文件传输协议 SCP(Secure Copy Protocol)被曝存在安全漏洞. 安全研究人员公布了 SCP 存在的多个漏洞,这些漏洞可以结合起来利用,分别为 CVE-2018-20 ...
- 互联网协议 — FTP 文件传输协议
目录 文章目录 目录 FTP vsftpd 自动模式和被动模式 PORT 主动模式 PASV 被动模式 访问控制方式 部署配置 FTP Server Global config Anonymous U ...
- FTP,SFTP,FTPS三个文件传输协议的区别
FTP,SFTP,FTPS三个文件传输协议的区别 文章目录: 简要说明 FTP(File Transfer Protocol):文件传送协议是 TCP/IP 协议组中的协议之一.FTP协议包括两个组成 ...
- 【计算机网络】应用层 : 总结 ( 网络应用模型 C/S P2P | 域名解析 DNS | 文件传输协议 FTP | 电子邮件 | 万维网 与 HTTP ) ★★★
文章目录 一.网络应用模型 ★ 二.域名解析过程 ★ 三.FTP 文件传输协议 四.电子邮件★ 五.万维网 和 HTTP 协议★ 一.网络应用模型 ★ 网络应用模型 : ① 客户 / 服务器 模型 ( ...
- 浅析文件传输协议 (ftp) 的工作原理
起初,FTP并不是应用于IP网络上的协议,而是ARPANEt网络中计算机间的文件传输协议, ARPANET是美国国防部组建的老网络,于1960-1980年使用.在那时, FTP的主要功能是在主机间高速 ...
最新文章
- 从抵触到力推,.Net Core 的成功让微软正视开源
- hdu4091(暴力)
- 2015/Province_C_C++_C/8/饮料换购
- python-第二块:time模块和datatime模块
- 解决升级 Office 2010 之后 Outlook 提示“无法打开 Microsoft Outlook”
- ieee754浮点数转换工具_关于JS浮点数运算不精确的原因和解决方案
- 以厘php框架 v10.6.8
- Python 2.7.X安装dpkt, sendpkt, pycap
- cartographer探秘之文章索引
- 注册测绘师成绩查询,2020注册测绘师成绩公布
- python3操作shp文件
- 21世纪的“影子王国”:GPT-3,又一场科技革命的来临
- 人工鱼群算法Matlab实现
- 简单聊聊电商系统的订单号生成规则
- 2016年全球半导体厂商TOP20排名
- Arduino /*传感器使用指南
- Python期末考试-中心点问题
- python爬虫爬取京东商品评价_python爬取京东商品信息及评论
- 一文了解循环神经网络
- 为何苹果电脑虚拟机如此受欢迎
热门文章
- 预告:揭秘7*24小时用数学解码交易的神秘玩家,量化交易者——TokenInsight对话首席...
- 通读c++ primer
- preg_replace() 正则替换所有符合条件的字符串
- 服务器是做什么用的?具体用途有哪些?
- FL Studio水果2023版本更新下载汉化教程
- win11怎么关闭自动更新系统
- 端午送粽子祝福微信小程序源码下载支持打赏模式带背景音乐
- iPad莫名其妙黑屏了,无法打开屏幕?
- 华为语音解锁设置_华为设置语音服务功能
- 重绘、重排区别及如何减少