词典项目练习

 思维导图

词典项目练习_第1张图片

 客户端

#include "head.h"
//用户提示界面
void help_info1()
{
	printf("\t-----------------------------------------------\n");
	printf("\t|               HENRY   在线辞典               |\n");
	printf("\t|版本:0.0.1                                    |\n");
	printf("\t|作者:Demons457                                |\n");
	printf("\t|功能:                                         |\n");
	printf("\t|    [1] 登录                                  |\n");
	printf("\t|    [2] 注册                                  |\n");
	printf("\t|    [3] 退出                                  |\n");
	printf("\t|注意:用户只有登录成功后才能进入查单词界面     |\n");
	printf("\t------------------------------------------------\n");
	return;
}
void help_info2()
{
	printf("\t-----------------------------------------------\n");
	printf("\t|     欢迎进入单词查询系统,很高兴为您服务     |\n");
	printf("\t|版本:0.0.1                                    |\n");
	printf("\t|作者:Demons457                                |\n");
	printf("\t|功能:                                         |\n");
	printf("\t|    [1] 查单词                                |\n");
	printf("\t|    [2] 查询历史记录                          |\n");
	printf("\t|    [3] 退出查询系统                          |\n");
	printf("\t|注意:用户只有登录成功后才能进入查单词界面     |\n");
	printf("\t------------------------------------------------\n");
	return;
}
 
 
//用户输入指令
enum{
	LOGIN    = 1,  //登陆
	REGISTER = 2,  //注册
	QUIT     = 3,  //退出
	QUERY    = 1,  //查询单词
	HISTORY  = 2,  //查询历史
};
 
int init_tcp(char *ip,char *port)
{
	int sockfd;
	struct sockaddr_in server_addr;
 
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		perror("Fail to socket");	
		exit(EXIT_FAILURE);
	}
 
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(atoi(port));
	server_addr.sin_addr.s_addr = inet_addr(ip);
 
	if(connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
	{
		perror("Fail to bind");	
		exit(EXIT_FAILURE);
	}
 
	return sockfd;
}
 
int do_register(int sockfd)
{
	int n = 0;
	int count = 0;
	char buf[1024] = {0};
	//定义发送的协议头
	mhead_t *head = (mhead_t *)buf;
 
	printf("\n您正在注册,请输入用户名和密码\n");
 
	head->type = USER_REGISTER;
	head->size = sizeof(mhead_t);
 
	printf("Input username : ");
	fgets(head->username,sizeof(head->username),stdin);
	head->username[strlen(head->username) - 1] = '\0';
 
	printf("Input password : ");
	fgets(head->password,sizeof(head->password),stdin);
	head->password[strlen(head->password) - 1] = '\0';
 
	//发给服务器端
	
	if(send(sockfd,buf,sizeof(mhead_t),0) < 0)
	{
		perror("Fail to send");
		exit(EXIT_FAILURE);
	}
	
	bzero(&buf,sizeof(buf));
	while(1)
	{
		//接收数据,TCP是可靠的连接,若是数据
		//未完全接收的话,可以在接收
		n = recv(sockfd,buf + count,sizeof(mhead_t) - count,0);
 
		if(n <= 0){
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
		//若是数据未发送完成,再次接收的时候可补充
		count += n;
		if(count == sizeof(mhead_t))
			break;
	}
 
	if(head->type == USER_SUCCESS)
	{
		printf("\n恭喜您,注册成功!\n");	
		return 0;
	}else{
		printf("\n很遗憾,这个用户名已经被其它用户注册过了,请重新注册");	
		return -1;
	}
 
}
int do_query(int sockfd)
{
	int n = 0;
	int fd;
	int count = 0;
	char buf[1024] = {0};
	char buf1[128]={0};
	char buf2[128]={0};
	char buf3[]="\n";
	fd=open("/home/linux/22061/2/client/history.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
	if(fd<0)
	{
	 perror("Fail to open");
	 return -1;
	}
	//定义发送的协议头
	mhead_t *head = (mhead_t *)buf;
 
	printf("\n您正在查询单词\n");
 
	head->type = USER_WORD;
	head->size = sizeof(mhead_t);
 
	printf("pelse input word : ");
	fgets(head->word,sizeof(head->word),stdin);
	head->word[strlen(head->word) - 1] = '\0';
    strcpy(buf1,head->word);
	if(send(sockfd,buf,sizeof(mhead_t),0) < 0)
	{
		perror("Fail to send");
		exit(EXIT_FAILURE);
	}
	
	bzero(&buf,sizeof(buf));
	while(1)
	{
		//接收数据
		//未完全接收的话,可以在接收
		n = recv(sockfd,buf + count,sizeof(mhead_t) - count,0);
 
		if(n <= 0){
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
		//若是数据未发送完成,再次接收的时候可补充
		count += n;
		if(count == sizeof(mhead_t))
			break;
	}
  //把服务器返回的信息打印出来
 	if(head->type == USER_SUCCESS)
	{
		printf(" word:%s\n",head->word);	
		time_t t;
		time(&t);
		sprintf(buf2,"\n%s\n",ctime(&t));
		write(fd,buf1,strlen(buf1));
		write(fd,buf2,strlen(buf2));
		write(fd,head->word,strlen(head->word));
		write(fd,buf3,strlen(buf3));
		close(fd);
		return 0;
	}else{
		printf("\n很遗憾,没有此单词,请重新输入\n");	
		return -1;
	}
   
}
int do_history(int sockfd)
{
  int fd,n;
  char buf[1024]={0};
  fd=open("/home/linux/22061/2/client/history.txt",O_RDONLY);
  if(fd<0)
  {
   perror("Fail to open");
   return -1;
  }
  while(1)
  {
   n=read(fd,buf,sizeof(buf));
   if(0==n)
	   break;
   puts(buf);
  }
  return 0;
}
int do_task2(int sockfd)
{
	int cmd;
	while(1)
	{
		//提示界面帮助,用户选择
		help_info2();	
 
		printf("\n\n请选择>");
		scanf("%d",&cmd);
		//吃掉回车键
		getchar();
		switch(cmd)
		{
			//用户查询单词
			case QUERY:
				if(do_query(sockfd) < 0)
					continue;
					break;
			//用户登陆
			case HISTORY:
					if(do_history(sockfd)<0)
					continue;
					 break;
			case QUIT:
				exit(EXIT_SUCCESS);
			default:
				printf("Unknow cmd.\n");
				continue;
		}
	}
	return 0;
}
 
int do_login(int sockfd)
{
	int n = 0;
	int count = 0;
	char buf[1024] = {0};
	//定义发送的协议头
	mhead_t *head = (mhead_t *)buf;
 
	printf("\n您正在登陆,请输入用户名和密码\n");
 
	head->type = USER_LOGIN;
	head->size = sizeof(mhead_t);
 
	printf("Input username : ");
	fgets(head->username,sizeof(head->username),stdin);
	head->username[strlen(head->username) - 1] = '\0';
 
	printf("Input password : ");
	fgets(head->password,sizeof(head->password),stdin);
	head->password[strlen(head->password) - 1] = '\0';
 
	//发给服务器端
	
	if(send(sockfd,buf,sizeof(mhead_t),0) < 0)
	{
		perror("Fail to send");
		exit(EXIT_FAILURE);
	}
	
	bzero(&buf,sizeof(buf));
	while(1)
	{
		//接收数据
		//未完全接收的话
		n = recv(sockfd,buf + count,sizeof(mhead_t) - count,0);
 
		if(n <= 0){
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
		//若是数据未发送完成,再次接收的时候可补充
		count += n;
		if(count == sizeof(mhead_t))
			break;
	}
 
	if(head->type == USER_SUCCESS)
	{
		printf("\n恭喜您,登陆成功!\n");	
		do_task2(sockfd);
		return 0;
	}else{
		printf("\n很遗憾,您的帐号或密码错误,请重新输入");	
		return -1;
	}
   
 
}
int do_task(int sockfd)
{
	int cmd;
	while(1)
	{
		//提示界面帮助,用户选择
		help_info1();	
 
		printf("\n\n请选择>");
		scanf("%d",&cmd);
		//吃掉回车键
		getchar();
		switch(cmd)
		{
			//用户注册
			case REGISTER:
				if(do_register(sockfd) < 0)
					continue;
					break;
			//用户登陆
			case LOGIN:
					if(do_login(sockfd)<0)
					continue;
					 break;
			case QUIT:
				exit(EXIT_SUCCESS);
			default:
				printf("Unknow cmd.\n");
				continue;
		}
	}
	return 0;
}
 
//由于后面要传递参数
int main(int argc, char *argv[])
{
	int sockfd;	
	int addr_len = sizeof(struct sockaddr);
	struct sockaddr_in peer_addr;
 
	if(argc < 3)
	{
		fprintf(stderr,"Usage : %s argv[1] argv[2]\n",argv[0]);	
		exit(EXIT_FAILURE);
	}
 
	sockfd = init_tcp(argv[1],argv[2]);
 
	do_task(sockfd);
 
	return 0;
}

服务器端

#include "head.h"
 
 
void signal_handler(int signum)
{
	waitpid(-1,NULL,WNOHANG);
	return;
}
int init_tcp(char *ip,char *port)
{
	int sockfd;
	struct sockaddr_in server_addr;
 
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		perror("Fail to socket");
		exit(EXIT_FAILURE);
	}
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port   = htons(atoi(port));
	server_addr.sin_addr.s_addr = inet_addr(ip);
 
	if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
	{
		perror("Fail to bind");
		exit(EXIT_FAILURE);
	}
	
	listen(sockfd,5);
	printf("listen....\n");
	return sockfd;
}
 
//数据库中手动创建2个表:user_table,word_table
int main(int argc, char *argv[])
{
	int pid;	
	sqlite3 *pdb;
	int listenfd,connect_fd;
	int addr_len = sizeof(struct sockaddr);
	struct sockaddr_in peer_addr;
 
	if(argc < 4)
	{
		fprintf(stderr,"Usage : %s ip port system.db.\n",argv[0]);
		exit(EXIT_FAILURE);
	}
 
	//探测子进程的改变状态,回收僵尸态子进程
	if(signal(SIGCHLD,signal_handler) == SIG_ERR)
	{
		perror("Fail to signal");
		exit(EXIT_FAILURE);
	}
 
	if(sqlite3_open(argv[3],&pdb) != SQLITE_OK)
	{
		fprintf(stderr,"sqlite3 open %s : %s.\n",argv[3],sqlite3_errmsg(pdb));
		exit(EXIT_FAILURE);
	}
 
	//初始化tcp连接,得到监听套接字
	listenfd = init_tcp(argv[1],argv[2]);
 
	//提取客户段的链接请求,创建子进程和客户端交互
	while(1)
	{
		if((connect_fd = accept(listenfd,(struct sockaddr *)&peer_addr,&addr_len)) < 0)
		{
			perror("Fail to accept");
			exit(EXIT_FAILURE);
		}
		
		if((pid = fork()) < 0)
		{
			perror("Fail to fork");
			exit(EXIT_FAILURE);
		}
 
		//创建子进程处理客户端的请求
		if(pid == 0){
			close(listenfd);
			do_client(connect_fd,pdb);
		}
		close(connect_fd);
	}
 
	exit(EXIT_SUCCESS);
}
#include "head.h" 
 
int do_register(int sockfd,sqlite3 *pdb,char *_username,char *_password)
{
	char *errmsg;
	char buf[1024];
	char **dbresult;
	int nrow = 0,ncolumn = 0;
	char sql[1024] = {0};
	mhead_t *head = (mhead_t *)buf;	
 
	sprintf(sql,"select * from user_table where NAME='%s';",_username);
	if(sqlite3_get_table(pdb,sql,&dbresult,&nrow,&ncolumn,&errmsg) != 0)
	{
		fprintf(stderr,"sqlite3 get table error : %s.\n",errmsg);
		exit(EXIT_FAILURE);
	}
 
	//没有这样的用户名
	if(nrow == 0)
	{
		//录入数据库
		bzero(sql,sizeof(sql));
		sprintf(sql,"insert into user_table values('%s','%s');",_username,_password);
		EXEC_SQL(pdb,sql,errmsg);
		
		printf("ok ........\n");
 
		head->type = USER_SUCCESS;
		if(send(sockfd,buf,sizeof(mhead_t),0) < 0)
		{
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
	//注册失败,用户名存在
	}else{
		head->type = USER_FAILURE;
		if(send(sockfd,buf,sizeof(mhead_t),0) < 0)
		{
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
		//表示未知
		printf("???????\n");
	}
	//插入到数据库之后,释放dbresult结果
	sqlite3_free_table(dbresult);
	return 0;
}
 
int do_login(int sockfd,sqlite3 *pdb,char *_username,char *_password)
{  
	char *errmsg;
	int i,j;
	char buf[1024];
	char **dbresult;
	int nrow = 0,ncolumn = 0;
	char sql[1024] = {0};
	mhead_t *head = (mhead_t *)buf;	
	char *zsql="select * from user_table";
	int index=0;
    //查找数据库中是否有该帐号
   //	sprintf(sql,"select * from user_table where NAME='%s';",_username);
	if(sqlite3_get_table(pdb,zsql,&dbresult,&nrow,&ncolumn,&errmsg) != 0)
	{
		fprintf(stderr,"sqlite3 get table error : %s.\n",errmsg);
		exit(EXIT_FAILURE);
	}
	//登陆
	for(i=0;i<=nrow;i++)
	{
	 for(j=0;jtype=USER_SUCCESS;
	   printf("%d\n",head->type);
	   if(send(sockfd,buf,sizeof(mhead_t),0)<0)
	   {
	    perror("Fail to send");
		exit(EXIT_FAILURE);
	   }
	   sqlite3_free_table(dbresult);
	   return 0;
	  }
	 }
	 index++;
	}
	//帐号密码错误
	head->type=USER_FAILURE;
	if(send(sockfd,buf,sizeof(mhead_t),0)<0)
	{
	   perror("Fail to send");
	   exit(EXIT_FAILURE);
	}
	printf("??????\n");
	sqlite3_free_table(dbresult);
	return 0;
}
int do_word(int sockfd,sqlite3 *pdb,char *_word)
{
	char *errmsg;
	int i,j;
	char buf[1024];
	char **dbresult;
	int nrow = 0,ncolumn = 0;
	char sql[1024] = {0};
	char *zsql="select * from dict_table";
	int index;
	mhead_t *head = (mhead_t *)buf;	
    //查找数据库中是否有该单词
	//sprintf(sql,"select * from dict_table where word='%s';",_word);
	if(sqlite3_get_table(pdb,zsql,&dbresult,&nrow,&ncolumn,&errmsg) != 0)
	{
		fprintf(stderr,"sqlite3 get table error : %s.\n",errmsg);
		exit(EXIT_FAILURE);
	}
    for(i=0;i<=nrow;i++)
	{
	  for(j=0;jtype=USER_SUCCESS;
		strcpy(head->word,dbresult[index+1]);
		if(send(sockfd,buf,sizeof(mhead_t),0)<0)
		{
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
		printf("%d\n",index);
		sqlite3_free_table(dbresult);
		return 0;
	   }
	   index++;
	  }
	}
	//查找失败,没有该单词
	head->type=USER_FAILURE;
	if(send(sockfd,buf,sizeof(mhead_t),0)<0)
	{
	  perror("Fail to send");
	  exit(EXIT_FAILURE);
	}
	printf("?????\n");
	sqlite3_free_table(dbresult);
	return 0;
}
int do_client(int sockfd,sqlite3 *pdb)
{
	int n;
	int count = 0;
	char buf[1024];
	mhead_t *head = (mhead_t *)buf;	
 
	while(1)
	{
		count = 0;
		//接收协议头
		while(1)
		{
			n = recv(sockfd,buf + count,sizeof(mhead_t) - count,0);
			if(n <= 0){
				exit(EXIT_FAILURE);
			}
 
			count += n;
			printf("count : %d mhead_t : %ld\n",count,sizeof(mhead_t));
			if(count == sizeof(mhead_t))
				break;
		}
 
		switch(head->type)
		{
		case USER_REGISTER:
			do_register(sockfd,pdb,head->username,head->password);	
			break;
		
		case USER_LOGIN:
			do_login(sockfd,pdb,head->username,head->password);
			break;
		case USER_WORD:
			do_word(sockfd,pdb,head->word);
			break;
		defalut:
			exit(EXIT_SUCCESS);
		}	
	}
 
	return 0;
}

你可能感兴趣的:(linux,学习)