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

📄 ftpdaemon.c

📁 模拟linux平台下边的vsFtp服务器可以实现文件的断点续传和下载
💻 C
字号:
#include "ftpdaemon.h"
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include "ftppub.h"
//#define MAX_BUFF_LEN 1024
#define SHORT_STR_LEN 256

//根据程序名获得其所有进程id号  由于要通过pidof这个命令来查询,为了获取pidof这个命令的结果,因此要用管道来保存查询结果
int getthispids(const char *appname,char *strpids,int bufflen)
{
	int pips[2];//pips是存来存管道的输入输出描述符
	pipe(pips);
	
	switch (fork())
	{
	case 0:	
		close(1);//关闭掉标准输出流描述符
		if (dup(pips[1])==-1)//dup函数这个是复制管道的输出流描述符,新描述符会从0来始查找还没有被使用的描述符做为新描述符
		{
			perror("dup");
		}
		close(pips[1]);//关闭管道的输出流描述符
		close(pips[0]);//关闭管道的输入流描述符

		//通过pidof这个命令来取得指定程 序名的所有进程id号
		execlp("pidof","pidof",appname,0);//用pidof这个命令程序来替换当前进程里边的代码
		exit(-1);
		break;
	case -1:
		exit(-1);
		break;
	default:
		close(pips[1]);
		read(pips[0],strpids,bufflen);
		close(pips[0]);
		return 0;
		break;
	}
}


int daemon_ctrl(int argc,char *argv[],int (*startfun)(void))
{
	//这个的作用是毕免子进程发生僵死进程
	signal(SIGCHLD, SIG_IGN);//当子进程发生子进程运行结束消息时,忽略掉这个消息

	if (argc !=2)
	{
		printf("Usage:miniftpd {start|stop|restart}\n");
		return -1;
	}
	if (strcmp(argv[1],"start")==0) //程序后连跟start参数 时执行startfun这个函数
	{
		return daemon_start(argv[0],startfun);
	}
	else if (strcmp(argv[1],"stop")==0) //程序后连跟stop参数 时执行startfun这个函数
	{	
		return daemon_stop(argv[0]);
	}
	else if (strcmp(argv[1],"restart")==0) //程序后连跟restart参数 时执行startfun这个函数
	{
		return daemon_restart(argv[0],startfun); 
	}
	else
		printf("Usage:ftpd {start|stop|restart}\n"); //程序后连跟其它字符串做参数 时执行提示只能跟这三个参数
	return -1;
}

//当参数为start时执行这个程 序
int daemon_start(char *app,int (*startfun)(void))
{
	//由于pidof这个命令只能在root用户下使用,所以这里要判断一下看看是不是以root用户启动
	if (getuid()!=0)
	{
		printf("请用root用户启动\n");
		exit(1);
	}
	int thisid=0;
	thisid=getpid();
	//printf("pid before invoke daemon=%d\n",thisid);
	char buff[BUFSIZ+1]={0};
	
	//获取这个程序所执行的所有进程号
	getthispids(app,buff,BUFSIZ);	
	
	char tmppid[SHORT_STR_LEN];
	char *p=buff;
	int tmpid,i=0;	
	
	while (*p)
	{
		while (*p&&isspace(*p))
			p++;
		i=0;
		while (*p&&!isspace(*p))
			tmppid[i++]=*p++;
		if (*p=='\0')
			break;
		tmpid=atoi(tmppid);
		if (thisid!=tmpid)
		{
			printf( "[ Service has been launched  ]\n");
			return -1;
		}
	}	

	char *strtmp="Ftp Server Start";
	write(1,strtmp,strlen(strtmp));	
	int pointcount=30;
	for (;pointcount>0;pointcount--) {
		write(1,".",1);
		usleep(10000);		
	}
	
	daemon(1,1);//这个是让当前进程变成守护进程
	
	
	//printf("pid after invoke daemon=%d\n",getpid());
	write(1,"[  OK  ]\n",strlen("[  OK  ]\n"));

	CreateShm();// 开启共享内存
	Create_Sem(4);//创建一个信号集,该 信号集中有4个信号量
	startfun();
	
	return 0;
}

//当参数为stop后就执行这个程 序
int daemon_stop(char *app)
{
	int thisid=0;
	thisid=getpid();
	
	char buff[BUFSIZ+1]={0};	
	
	getthispids(app,buff,BUFSIZ);	
	
	
	char tmppid[SHORT_STR_LEN];
	char *p=buff;

	int tmpid,i=0;	
	
	if (!strchr(buff,' '))
	{
		//当前只有一个进程
		printf( "[ Services are not running  ]\n");
		return -1;
	}
	char *strtmp="Ftp Server Stop ";
	write(1,strtmp,strlen(strtmp));	
	while (*p)
	{
		while (*p&&isspace(*p))p++;
		i=0;
		while (*p&&!isspace(*p))
			tmppid[i++]=*p++;
			
		tmpid=atoi(tmppid);
		if (tmpid!=0&&thisid!=tmpid)
		{
			kill(tmpid,SIGTERM);		//杀死进程
		}
		memset(tmppid,0,SHORT_STR_LEN);
		if(*p=='\0')	break;
	}
	CreateShm();//在关闭进程中这个是一个新的进程
	Removeshm(g_shmid);//关闭掉共享内存

	Create_Sem(4);
	del_semvalue(sem_id);
	
	int pointcount=10;
	for (;pointcount>0;pointcount--) {
		write(1,".",1);
		usleep(10000);		
	}
	write(1,"[  OK  ]\n",strlen("[  OK  ]\n"));	

	return 0;
}

//当参数为restart后就执行这个程 序
int daemon_restart(char *app,int (*startfun)(void))
{
	daemon_stop(app);
	usleep(100000);//??????????kill需要一定时间
	return daemon_start(app,startfun);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -