📄 ftpd.c
字号:
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "ftpdaemon.h"
#include "ftpnet.h"
#include "ftppub.h"
#include "ftpcmd.h"
#include <errno.h>
#define INFO_BUFF_SIZE 100
//程序中所有的全局变量都在这里被定义
int connected_socket;//connected_socket这个是已连接套接字,用来跟客户端进行命令传输
int datatrans_socket;//这个套接字用来跟客户端进行数据传输
int IsPASV=1;//用来标识被动模式
int IsAnonymous;//标记当前登入用户是否是匿名用户
char userName[512];//全局变量userName用来保存用户名
char path[PATH_MAX+1];
int userlogined=0;//标记用户以登入
int pasv_datatrans_socket;//用在被动模式下进行数据传输
int pasv_listen_socket;//用在被动模式下进行监听的套接字
int timeout=10;//这里定超时10秒后
int is_have_timeout=1;//用来标识现在是否有进行超时,默认情况下有进行超时,当值为1时有进行超时 值为0时不进行超时
int child_pid;//保存子进程ID
long offset=0;//在断点续传中SERT指令要用的
int transfers_mode=0;//定义传输模式 0为普通模式,即没有采用断点续传模式 1为 APPE断点续传模式 2为REST断点续传模式
char anonymous_dir[PATH_MAX+1]={0};//匿名用户的根目录
char cur_anonymous_dir[PATH_MAX+1]={0};//匿名用户的物理地址
char oldpath[PATH_MAX+1]={0};//这个字符数组用来在进行重命的时候用
int g_isupload=0;//是否在上传
int g_isdownload=0;//是否在下载
int downspeed;//限制下载速 度
int upspeed;//限制上传速 度
int g_shmid=0;//共享内存标识
int sem_id;//信号集标识
int port_no=21;//端口号
FLUXCTRL * g_segptr;//指向服务器共享信息结构体
int ftp_server_start()
{
//读取出配制信息
int size=5;
int alreadyRead=0;//存放以读取配制信息的个数
//测试接收配制文件
struct configInfo * config=(struct configInfo *)malloc(sizeof(struct configInfo)*size);
//取出配制信息
if(ReadConfigInfo(config,size,&alreadyRead)==1)
{
int i=0;
for(;i<alreadyRead;i++)
{
// printf("\n名称为:%s , 值为: %s\n",config[i].keyname,config[i].value);
if(strcmp(config[i].keyname,"maxup")==0)
{
upspeed=atoi(config[i].value);
// printf("第%d个,上传最大......................[%d]\n",i,upspeed);
}else if(strcmp(config[i].keyname,"maxdown")==0)
{
downspeed=atoi(config[i].value);
// printf("第%d个,下载最大......................[%d]\n",i,downspeed);
}else if(strcmp(config[i].keyname,"timeout")==0)
{
timeout=atoi(config[i].value);
// printf("第%d个,超时..........................[%d]\n",i,timeout);
}else if(strcmp(config[i].keyname,"port_no")==0)
{
port_no=atoi(config[i].value);
// printf("第%d个,端口号........................[%d]\n",i,port_no);
}
}
}
else
{
printf("读取配制文件出错\n");
exit(1);
}
struct sockaddr_in socketaddr;
int listen_sock;//监听套接字
int childpid,state;
//socklen_t len;//存放套接字地址长度
memset(&socketaddr, 0, sizeof(socketaddr));//将套接字地址清零
listen_sock=CreateSocket();//创建一个监听套接字
if(listen_sock<0)
{
printf("创建套接字失败");
exit(-1);
}
// printf("绑定端口号是...............[%d]\n",port_no);
init_socket_addr(&socketaddr,0,port_no);
state=bind_socket(listen_sock,&socketaddr);
if(state<0)
{
printf("绑定出错");
exit(-1);
}
state=listen_socket(listen_sock,10);//第二个参数10代表的是同一时刻最多连接10个用户
if(state)
{
printf("监听出错");
exit(-1);
}
signal(SIGCHLD, SIG_IGN);//防止子进程结束后变成僵死进程,这里子进程结束后会产生SIGCHLD信号,当父进程接收到这个信号时忽略掉
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
// signal(SIGTERM,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
for (;;)
{
//pause();
// printf("进入等待用户连接...\n");
connected_socket=accept_socket(listen_sock,&socketaddr);
// printf("有一用户连接连接进来...\n");
// printf("connected_socket=%d",connected_socket);
if(connected_socket<0)
{
//"接收用户请求时连接出错"
continue;
}
else
{
if(0==(childpid=fork()))//当childpid的值==0的时候代表的是子进程
{
signal(SIGUSR1,start_timeout);//SIGUSR1信号在这里的作用是由负责数据传输的进程向父进程发送,当父进程接收到信号后就开启超时
//Attach_Shm(g_shmid);
//在fork出来的子进程中accept_sock套接字跟父进程中的accept_sock同指向一个内核缓冲区
//在子进程中不需要监听套接字所以关掉
close(listen_sock);//关闭掉监听套接自
char recv_info_buffer[INFO_BUFF_SIZE]={0};//存放客户端发送给服务端的消息 例客户端发送的信息为 abc\r\n 的字符串,这里的字符串不会以'\0'结尾
char cmd_buf[CMD_BUFF_SIZE]={0};//命令缓冲区
Respond(220,"welcome to login miniftpd 1.0");
int i=0;
int res;
while(1)
{
//超时处理中, 由于在超时时
if((res=Is_Time_Out(connected_socket, timeout))==0)//传入connected_socket,判断sec时间内是否超时,返回值大于0代表有多少个可读事件,超时返回0,错误返回-1
{
if(is_have_timeout==1)//代表现在有进行数据传送,传输命令不进行超时
{
exit(1);
}else
{
continue;
}
}
else if(res==1)
{
memset(recv_info_buffer,0,sizeof(recv_info_buffer));//这里一定要清缓冲区
my_read(connected_socket,recv_info_buffer,INFO_BUFF_SIZE);
}
else
{
//perror("DDDDDDDDDDDD");
//printf("DDDDDDDDDD=%d\n",errno);
//exit(1);
continue;
}
i=0;
// printf("接收的消息是: %s 结束\n",recv_info_buffer);
memset(cmd_buf,0,sizeof(cmd_buf));
Intercept_Command(cmd_buf,recv_info_buffer);
// printf("命令: %s\n",cmd_buf);
/*
for(i=0;;i++)
{
if(strcmp(cmd_list[i].cmd,"") == 0)
{
Respond(500,"Unknown command.");
break;
}
if(strcmp(cmd_list[i].cmd,cmd_buf)==0)
{
(cmd_list[i].cmd_handler)(recv_info_buffer);
break;
}
}
*/
while(strcmp(cmd_list[i].cmd,"")!=0)
{
if(strcmp(cmd_list[i].cmd,cmd_buf)==0)
{
//
// if(strcmp(cmd_list[i].cmd,"STAT")==0)
// {
// printf("开始执行......................%s 命令,其函数指针的值是 %d\n",cmd_buf,(int)(cmd_list[i].cmd_handler));
// //do_stat(recv_info_buffer);
// }
if(cmd_list[i].cmd_handler==NULL)
{
Respond(500,"Unknown command.");
}
else
{
(cmd_list[i].cmd_handler)(recv_info_buffer);
}
break;
}
//printf("执行结构体数组中的第 %d 个命令\n",i);
i++;
}
if(strcmp(cmd_list[i].cmd,"")==0)
{
if(cmd_buf[0]!=-1)
{
// printf("非法字符的内容为.............[ %s ]\n",cmd_buf);
// printf("第一个非法字符%d,%d\n",cmd_buf[0],cmd_buf[1]);
Respond(500,"Unknown command.");
}
}
}
close(connected_socket);
exit(0);
}
}
close(connected_socket);
}
}
int main(int argc,char *argv[])
{
//创建Ftp守护进程
return daemon_ctrl(argc,argv,ftp_server_start);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -