电子词典。登录注册功能,不能重复登录,重复注册 单词查询功能 历史记录功能,存储单词,意思,以及查询时间 基于TCP,支持多客户端连接 采用数据库保存用户信息与历史记录 将dict.txt的数据导入到

//服务器

#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>

#define ERR_MGS(m) do{\
	fprintf(stderr,"__%d\t__",__LINE__);\
	perror(m);\
}while(0)

int do_inter(int newfd,struct sockaddr_in sind,sqlite3* db);
int import(sqlite3* db);
void handler(int arg){
	while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{
	//打开数据库
	sqlite3 *db;
	if(sqlite3_open("./sq.db",&db)!=0){
		fprintf(stderr,"line:%d sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
		fprintf(stderr,"line:%d sqlite3_open:%d\n",__LINE__,sqlite3_errcode(db));
		return 0;
	}
	printf("打开数据库成功\n");

	//将文件导入数据库
	import(db);
	//用信号函数循环回收僵尸进程,为下面使用多进程并发服务器做铺垫
	__sighandler_t s=signal(17,handler);
	if(SIG_ERR==s){
		ERR_MGS("signal");
		return 0;
	}
	//创建套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(-1==sfd){
		ERR_MGS("socket");
		return 0;
	}
	//允许端口快速重用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0)
	{
		ERR_MGS("setsockopt");
		return -1;
	}
	//将ip和端口号绑定在套接字上
	//定义地址族变量
	struct sockaddr_in sin;
	//填充地址信息结构体
	sin.sin_family=AF_INET;
	sin.sin_port=htons(8888);
	sin.sin_addr.s_addr=inet_addr("192.168.8.214");
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
		ERR_MGS("bind");
		return 0;
	}
	//将套接字设置为被动监听状态
	if(listen(sfd,88)<0){
		ERR_MGS("listen");
		return 0;
	}
	//定义结构体变量和其他变量用于下面的逻辑
	struct sockaddr_in sind;
	socklen_t addrlen=sizeof(sind);
	pid_t pid;
	int newfd;
	//使用多进程并发服务器实现多个客户端同时在线
	while(1){
		//父进程循环连接客户端
		newfd=accept(sfd,(struct sockaddr*)&sind,&addrlen);
		if(newfd<0){
			ERR_MGS("accept");
			return 0;
		}
		printf("[%s %d] newfd=%d\n",inet_ntoa(sind.sin_addr),ntohs(sind.sin_port),newfd);	
		if((pid=fork())==0){
			//关闭无用的文件描述符
			close(sfd);
			//调用交互函数
			do_inter(newfd,sind,db);
			//退出进程
			exit(0);
		}else if(pid>0){
			close(newfd);		
		}else{
			ERR_MGS("fork");
			return 0;
		}

	}
	return 0;
}
//导入数据库
int  import(sqlite3* db){

	//打开要导入的文件
	FILE* fd=fopen("../dict.txt","r");
	if(fd<0){
		perror("open");
		return 0;
	}
	printf("打开文件成功\n");
	//创建一张表格
	char c[128]="create table if not exists stu3(name char,chinese char)";
	char *errmsg=NULL;
	if(sqlite3_exec(db,c,NULL,NULL,&errmsg)){
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
		fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
		return 0;
	}
	printf("创建成功\n");
	char chinese[200]="";
	char name[128]="";
	char buf[300]="";
	char d[500]="";
	//将文件中的数据储存到name和chinese中;
	while(fgets(buf,sizeof(buf),fd)!=NULL){
		char* p=buf;
		while(1){			
			if(*p!=' ' || (*p != ' ' && *(p+1) != ' ')){
				p++;

			}else {
				break;
			}
		}
		*p='\0';
		p++;
		strcpy(name,buf);
		while(*p==' '){
			p++;
		}
		strcpy(chinese,p);
		//循环存入到数据库中
		sprintf(d,"insert into stu3 values(\"%s\",\"%s\");",name,chinese);
		if(sqlite3_exec(db,d,NULL,NULL,&errmsg)!=0){
			fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
			fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
			return 0;
		}
		bzero(d,sizeof(d));
		bzero(buf,sizeof(buf));
		bzero(name,sizeof(name));
		bzero(chinese,sizeof(chinese));
	}

	printf("数据导入完成.....\n");

}
//与客户端交互
int do_inter(int newfd,struct sockaddr_in sind,sqlite3* db){
	char buf[256]="";
	char bbuf[256]="";
	char name2[128]="";
	char name3[128]="";
	//接收客户端信息
	ssize_t res,red;
	int falg=0;
	int fad=0;
	int std=0;
	//定义数据库需要的变量
	int line;
	int list;
	char **ptr;
	umask(0);

	while(1){
		FILE* fd=fopen("hello.txt","r+");
		if(fd<0){
			ERR_MGS("fopen");
			return 0;
		}
DNG:
SND:
FSP:
		bzero(buf,sizeof(buf));
		bzero(bbuf,sizeof(bbuf));
		res=recv(newfd,buf,sizeof(buf),0);
		if(0==res)
		{

			if(buf[0]=='Q'){
				char bsp[128]="";
				sprintf(bsp,"delete from stu5 where name=\"%s\";",buf+1);
				char* errmsg=NULL;
				if(sqlite3_exec(db,bsp,NULL,NULL,&errmsg)!=0){
					printf("line: %d sqlite3_close :%s\n",\
							__LINE__,errmsg);
					return 0;

				}
				printf("delete success\n");

				printf("用户%s已退出\n",buf+1);
				goto DNG;

			}

		}else if(-1==res){
			ERR_MGS("recv");	
			return 0;
		}
		//退出逻辑
		if(buf[0]=='Q'){
			printf("--%d--\n",__LINE__);
			char bsp[128]="";
			char fdd[128]="";
			char spp[128]="";
			res=recv(newfd,fdd,sizeof(fdd),0);
			if(-1==res){
				ERR_MGS("recv");	
				return 0;
			}
			strcpy(spp,buf+1);
			strcat(spp,fdd);

			sprintf(bsp,"delete from stu5 where name=\"%s\";",spp);

			char* errmsg=NULL;
			if(sqlite3_exec(db,bsp,NULL,NULL,&errmsg)!=0){
				printf("line: %d sqlite3_close :%s\n",\
						__LINE__,errmsg);
				return 0;

			}
			printf("delete success\n");

			printf("用户%s已退出\n",buf+1);
			goto DNG;

		}
		//注册逻辑
		if(buf[0]=='Z'){
			int pdd=fseek(fd,0,SEEK_SET);
			while(1){
				falg=0;
				red=fscanf(fd,"%s",bbuf);

				if(red<0){
					printf("文件校验完毕\n");
					break;
				}		
				if(strcmp(bbuf,buf+1)==0){
					bzero(bbuf,sizeof(bbuf));
					strcpy(bbuf,"The user name exists");
					if(send(newfd,bbuf,sizeof(bbuf),0)<0){
						ERR_MGS("send");
						break;
					}
					falg=1;
					break;
				}

			}

			if(falg==0){
				fseek(fd,0,SEEK_END);
				fprintf(fd,"%s\n",buf+1);
				fflush(fd);

				bzero(bbuf,sizeof(bbuf));
				strcpy(bbuf,"Registration Successful");
				if(send(newfd,bbuf,sizeof(bbuf),0)<0){
					ERR_MGS("send");
					break;
				}
			}
			fclose(fd);
		}
		//登录逻辑
		if(buf[0]=='D'){
			fad=0;
			int add=fseek(fd,0,SEEK_SET);
			printf("%d\n",add);
			while(1){
				fad=0;
				red=fscanf(fd,"%s",bbuf);

				if(red<0){
					printf("文件校验完毕\n");
					break;
				}		
				if(strcmp(bbuf,buf+1)==0){

					printf("该用户存在\n");
					fad=1;
					break;
				}

			}
			if(fad==1){
				//创建一张表格

				char c[128]="create table if not exists stu5(name char primary key)";
				char *errmsg=NULL;
				if(sqlite3_exec(db,c,NULL,NULL,&errmsg)){
					fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
					fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
					return 0;
				}
				printf("创建成功\n");
			}
			while(1){
				falg=0;	
				//查找表格中是否有登录信息
				char cd[128]="select* from stu5";
				char *errmsg=NULL;
				if(sqlite3_get_table(db,cd,&ptr,&line,&list,&errmsg)!=0){
					fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
					fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
					return 0;
				}
				for(int i=0;i<(line+1)*list;i++){
					if(strcmp(ptr[i],buf+1)==0){
						bzero(bbuf,sizeof(bbuf));
						strcpy(bbuf,"User logged in");
						if(send(newfd,bbuf,sizeof(bbuf),0)<0){
							ERR_MGS("send");
							break;
						}
						falg=1;
						goto SND;
					}

				}
				//将登录信息插入到表格中去
				if(falg==0){
					bzero(cd,sizeof(cd));	
					sprintf(cd,"insert into stu5 values(\"%s\")",buf+1);
					if(sqlite3_exec(db,cd,NULL,NULL,&errmsg)!=0){
						fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
						fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
						return 0;

					}
					printf("登录信息插入表格成功\n");
					bzero(bbuf,sizeof(bbuf));
					strcpy(bbuf,"Login successfully");
					if(send(newfd,bbuf,sizeof(bbuf),0)<0){
						ERR_MGS("send");
						break;
					}

					goto DNG;
				}

			}
		}
		bzero(bbuf,sizeof(bbuf));
		strcpy(bbuf,"The user does not exist");
		if(send(newfd,bbuf,sizeof(bbuf),0)<0){
			ERR_MGS("send");
			break;
		}
		fclose(fd);
	}
	//查单词逻辑
	if(buf[0]=='C'){
		res=recv(newfd,name2,sizeof(name2),0);
		if(0==res){
			printf("用户已退出\n");	
			return 0;
		}else if(-1==res){
			ERR_MGS("recv");	
			return 0;
		}

		char fu[128]="";
		sprintf(fu,"select* from stu3 where name=\"%s\";",buf+1);
		char** ptr;
		int row,nom;
		char* errmsg=NULL;
		if(sqlite3_get_table(db,fu,&ptr,&row,&nom,&errmsg)!=0){
			printf("line: %d sqlite3_close :%s\n",\
					__LINE__,errmsg);
			bzero(fu,sizeof(fu));	
			strcpy(fu,"The word does not exist");
			if(send(newfd,fu,sizeof(fu),0)<0){
				ERR_MGS("send");
				return 0;
			}
			goto FSP;
		}
		printf("updata success\n");
		bzero(fu,sizeof(fu));
		strcpy(fu,ptr[2]);
		strcat(fu," ");
		strcat(fu,ptr[3]);
		if(send(newfd,fu,sizeof(fu),0)<0){
			ERR_MGS("send");
			return 0;
		}
		//创建一张表格用来储存历史信息

		char bpf[256]="";
		if(std==0){
			strcpy(bpf,"create table if not exists stu4(name char,word char,time char)");

			if(sqlite3_exec(db,bpf,NULL,NULL,&errmsg)){
				fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
				fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
				return 0;
			}
			printf("创建成功\n");
			std=1;
		}
		//获取时间
		time_t t,t1;
		t1=time(&t);
		struct tm* info=NULL;
		info=localtime(&t1);
		char time[256]="";
		strftime(time,sizeof(time),"%Y-%m-%d %H:%M:%S",info);
		//将历史信息插入到数据库中
		bzero(bpf,sizeof(bpf));	
		sprintf(bpf,"insert into stu4 values(\"%s\",\"%s\",\"%s\")",name2,fu,time);
		if(sqlite3_exec(db,bpf,NULL,NULL,&errmsg)!=0){
			fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
			fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
			return 0;

		}
		printf("历史信息插入表格成功\n");

	}	
	//查历史记录逻辑
	if(buf[0]=='H'){
		//查询表格中对应姓名的历史记录
		char fu[512]="";
		sprintf(fu,"select* from stu4 where name=\"%s\";",buf+1);
		char** ptr;
		int row,nom;
		char* errmsg=NULL;
		if(sqlite3_get_table(db,fu,&ptr,&row,&nom,&errmsg)!=0){
			printf("line: %d sqlite3_close :%s\n",\
					__LINE__,errmsg);
		}
		printf("updata success\n");
		int i;
		for(i=nom;i<(row+1)*nom;i+=nom){
			printf("111\n");	
			bzero(fu,sizeof(fu));
			strcpy(fu,ptr[i]);
			strcat(fu," ");
			strcat(fu,ptr[i+1]);
			fu[strlen(fu)-1]='\0';
			strcat(fu," ");
			strcat(fu,ptr[i+2]);
			printf("%s\n",fu);	
			if(send(newfd,fu,sizeof(fu),0)<0){
				ERR_MGS("send");
				return 0;
			}
		}
		bzero(fu,sizeof(fu));
		strcpy(fu,"-1");
		if(send(newfd,fu,sizeof(fu),0)<0){
			ERR_MGS("send");
			return 0;
		}

		printf("查询完成\n");

	}	
}

//客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>

#define ERR_MGS(m)do{\
	fprintf(stderr,"%d\n",__LINE__);\
	perror(m);\
}while(0)
int scoketd;
char name1[128]="";
char paw1[128]="";
void do_find(int scoketd,char* name1);
void do_past(int scoketd,char* name1);
void handler(int arg){
	char pass[128]="";
	pass[0]='Q';
	strcat(pass,name1);
	strcat(pass,paw1);
	int rad=send(scoketd,pass,sizeof(pass),0);
	if(rad<0){
		ERR_MGS("send");
		return ;
	}
	kill(0,9);


}
int main(int argc, const char *argv[])
{
	//基于TCP的客户端模型
	//创建一个信号函数用来捕捉二号信号
	__sighandler_t s=signal(2,handler);
	if(SIG_ERR==s){
		ERR_MGS("signal");
		return 0;
	}
	//创建套接字
	scoketd=socket(AF_INET,SOCK_STREAM,0);
	if(-1==scoketd){
		ERR_MGS("scoket");
		return 0;
	}
	//允许端口快速重用
	int reuse = 1;
	if(setsockopt(scoketd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0)
	{
		ERR_MGS("setsockopt");
		return -1;
	}
	printf("创建套接字成功\n");
	//连接到服务器
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(8888);
	sin.sin_addr.s_addr=inet_addr("192.168.8.214");
	socklen_t addrlen1=sizeof(sin);

	int fpd=connect(scoketd,(struct sockaddr*)&sin,addrlen1);
	if(-1==fpd){
		ERR_MGS("connect");
		return 0;
	}
	printf("连接服务器成功\n");

	//定义菜单需要的的变量
	int num;
	char name[128]="";
	char paw[128]="";
	char pass[256]="";
	ssize_t rad;
SFD:
	//登录菜单
	while(1){
		system("clear");
		printf("<<<欢迎使用电子词典>>>\n");
		printf("**********************\n");
		printf("*********1.注册********\n");
		printf("*********2.登录********\n");
		printf("*********3.退出********\n");
		printf("***********************\n");
		printf("请输入您要选择的功能\n");
		scanf("%d",&num);
		while(getchar()!=10);
		switch(num){
			//注册	
		case 1:
			bzero(name,sizeof(name));
			bzero(paw,sizeof(paw));
			bzero(pass,sizeof(pass));
			pass[0]='Z';
			printf("请输入要注册的用户名\n");
			scanf("%s",name);
			while(getchar()!=10);
			printf("请输入要注册的密码\n");
			scanf("%s",paw);
			while(getchar()!=10);
			strcpy(pass+1,name);
			strcat(pass,paw);
			rad=send(scoketd,pass,sizeof(pass),0);
			if(rad<0){
				ERR_MGS("send");
				return 0;
			}
			bzero(pass,sizeof(pass));
			if(recv(scoketd,pass,sizeof(pass),0)<0){
				ERR_MGS("recv");
				return 0;
			}
			if(strcmp(pass,"Registration Successful")==0){
				printf("注册成功\n");
			}else if(strcmp(pass,"The user name exists")==0){
				printf("用户名已存在\n");
			}
			break;
			//登录	
		case 2:
			bzero(name,sizeof(name));
			bzero(paw,sizeof(paw));
			bzero(pass,sizeof(pass));
			pass[0]='D';
			printf("请输入用户名\n");
			scanf("%s",name);
			while(getchar()!=10);
			strcpy(name1,name);
			printf("请输入密码\n");
			scanf("%s",paw);
			strcpy(paw1,paw);
			while(getchar()!=10);
			strcpy(pass+1,name);
			strcat(pass,paw);
			rad=send(scoketd,pass,sizeof(pass),0);
			if(rad<0){
				ERR_MGS("send");
				return 0;
			}
			bzero(pass,sizeof(pass));
			if(recv(scoketd,pass,sizeof(pass),0)<0){
				ERR_MGS("recv");
				return 0;
			}

			if(strcmp(pass,"User logged in")==0){
				printf("该用户已登录,登录失败\n");
			}else if(strcmp(pass,"Login successfully")==0){
				printf("登录成功\n");
				goto PDD;
			}else{
				printf("该用户不存在\n");
			}

			break;
			//退出	
		case 3:
			goto END;
			break;
		default:
			printf("输入错误请重新输入\n");
			break;
		}
		printf("按下任意字符清屏\n");
		while(getchar()!=10);
	}
	//二级菜单
	while(1){
PDD:
		system("clear");
		printf("*****欢迎使用电子词典******\n");
		printf("*******1.查单词***********\n");
		printf("*******2.查历史记录*******\n");
		printf("*******3.返回上级菜单*******\n");
		printf("**************************\n");
		printf("请输入您要选择的功能\n");
		scanf("%d",&num);
		while(getchar()!=10);
		switch(num){
		case 1:
			//查单词
			do_find(scoketd,name1);
			break;
		case 2:
			//查历史记录
			do_past(scoketd,name1);
			break;
		case 3:
			//返回之前给服务器发一个信号,代表用户已经退出了
			bzero(pass,sizeof(pass));
			pass[0]='Q';
			strcat(pass,name1);
			if(send(scoketd,pass,sizeof(pass),0)<0){
				ERR_MGS("send");
				return 0;
			}
			if(send(scoketd,paw1,sizeof(paw1),0)<0){
				ERR_MGS("send");
				return 0;
			}


			//返回上级菜单

			goto SFD;
			break;
		default:
			break;

		}
		printf("按下任意字符清屏\n");
		while(getchar()!=10);
	}
END:
	//关闭文件描述符
	close(scoketd);
	return 0;
}
//查单词
void do_find(int scoketd,char* name1){
	char buf[256]="";
	int rad;
	while(1){
		bzero(buf,sizeof(buf));		
		printf("请输入您要查的单词或按#退出\n");
		buf[0]='C';
		scanf("%s",buf+1);
		getchar();
		if(strcmp(buf+1,"#")==0){
			break;
		}
		rad=send(scoketd,buf,sizeof(buf),0);
		if(rad<0){
			ERR_MGS("send");
			return ;
		}
		rad=send(scoketd,name1,strlen(name1),0);
		if(rad<0){
			ERR_MGS("send");
			return ;
		}

		bzero(buf,sizeof(buf));
		if(recv(scoketd,buf,sizeof(buf),0)<0){
			ERR_MGS("recv");
			return ;
		}
		if(strcmp(buf,"The word does not exist")==0){
			printf("未查询到该单词\n");
		}else{
			printf("%s",buf);
		}
	}

}
//查历史记录
void do_past(int scoketd,char* name1){
	char buf[512]="";
	buf[0]='H';
	strcat(buf,name1);
	int rad=send(scoketd,buf,sizeof(buf),0);
	if(rad<0){
		ERR_MGS("send");
		return ;
	}
	bzero(buf,sizeof(buf));
	while(1){
		if(recv(scoketd,buf,sizeof(buf),0)>0){
			if(strcmp(buf,"-1")==0){
				break;
			}
		}
		printf("%s\n",buf);
		bzero(buf,sizeof(buf));

	}

	printf("信息查询完毕,输入任意字符退出查询\n");
	while(getchar()!=10);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值