利用多线程实现基于TCP的电子词典

ser.c

#include <head.h>
//定义线程体结构体
struct cli_msg
{
	int newfd;
	struct sockaddr_in cin;
	sqlite3 **db;
};
//定义信息结构体
typedef struct MSG
{
	char code;//'L':登录 'E':注册 'Q':退出 'F':查询单词 'S':查询历史记录
	char user[9];
	char passwd[9];
	char msg[128];
}msg_t;
//添加用户信息
int do_add_user(sqlite3 *db,msg_t buf);
//创建电子词典数据库
int create_dictionary_db(sqlite3 **db);
//创建用户表
int create_user_table(sqlite3 **value);
//定义查找用户
int do_search_user(sqlite3 *db,msg_t buf);
//关闭数据库
int close_dictionary_db(sqlite3 **db);
//定义查找密码
int do_search_pass(sqlite3 *db,msg_t buf);
//定义注册功能
void use_register(sqlite3 **db,msg_t buf,int newfd);
//定义登录功能
void user_login(sqlite3 **db,msg_t buf,int newfd,char *user);
//创建单词表
int create_word_table(sqlite3 **value);
//添加单词信息
int do_add_word(sqlite3 **value);
//定义查找单词功能
void do_search_word(sqlite3 **value,msg_t buf,char *user,int newfd);
//创建历史记录表
int create_history_table(sqlite3 *db,msg_t buf);
//添加历史信息
int do_add_history(sqlite3 *db,char *user,char *English,char *Chinese);
//定义查找历史记录
int do_search_history(sqlite3 **value,msg_t buf,int newfd,char *user);

void *deal_cli_msg(void *arg)
{

	int newfd=((struct cli_msg*)arg)->newfd;
	struct sockaddr_in cin =((struct cli_msg*)arg)->cin;
	sqlite3 **db=((struct cli_msg*)arg)->db;
	msg_t buf;
	char user[36]="";
	while(1)
	{
		int flag;
		bzero(&buf.msg,sizeof(buf.msg));
		int ret=recv(newfd,&buf,sizeof(buf),0);
		if(ret==-1)
		{
			ERR_MSG("recv");
		}else if(ret==0)
		{
			printf("%s:客户端下线\n",buf.user);
			break;
		}
		printf("%s : %c \n",buf.user,buf.code);
		//-------------------------发送
		switch(buf.code)
		{
		case 'E':
			use_register(db,buf,newfd);			
			break;
		case 'L':
			user_login(db,buf,newfd,user);
			break;
		case 'F':
			puts(user);
			do_search_word(db,buf,user,newfd);
			break;
		case 'S':
			do_search_history(db,buf,newfd,user);
			break;
		}
	}
}

//定义注册功能
void use_register(sqlite3 **db,msg_t buf,int newfd)
{
	int flag;
	char sen[128];
	flag=do_search_user(*db,buf);
	if(flag==0)//0表示不存在
	{
		do_add_user(*db,buf);
		bzero(buf.msg,sizeof(buf.msg));
		strcpy(buf.msg,"register success");
		//创建历史记录表
		create_history_table(*db,buf);
		if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
		{
			ERR_MSG("send");
		}
	}
	else if(flag==1)//1:表示存在
	{
		bzero(buf.msg,sizeof(buf.msg));
		strcpy(buf.msg,"user exist");
		if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
		{
			ERR_MSG("send");
		}
	}

}
//定义登录功能
void user_login(sqlite3 **db,msg_t buf,int newfd,char *user)
{
	int flag;
	flag=do_search_user(*db,buf);
	if(flag==0)//0表示不存在
	{
		bzero(buf.msg,sizeof(buf.msg));
		strcpy(buf.msg,"user unexist");
		if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
		{
			ERR_MSG("send");
		}
	}
	else if(flag==1)//1:表示存在
	{
		flag=do_search_pass(*db,buf);
		if(flag==1)
		{
			bzero(buf.msg,sizeof(buf.msg));
			strcpy(buf.msg,"login success");
			strcpy(user,buf.user);
			if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
			{
				ERR_MSG("send");
			}
		}
		else 
		{
			bzero(buf.msg,sizeof(buf.msg));
			strcpy(buf.msg,"passwd error");
			if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
			{
				ERR_MSG("send");
			}
		}
	}
}
//创建电子词典数据库
int create_dictionary_db(sqlite3 **db)
{
	if(sqlite3_open("./dictionary.db",db)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_open error,errcode:%d,errmsg:%s\n",__LINE__,sqlite3_errcode(*db),sqlite3_errmsg(*db));
		return -1;
	}
	printf("sqlite3_open success\n");
	return 0;
}
//创建用户表
int create_user_table(sqlite3 **value)
{
	sqlite3 *db=*value;
	char sql[]="create table if not exists User_t(user char primary key,passwd char);";
	//定义接收错误信息的指针
	char *errmsg=NULL;
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
		sqlite3_free(errmsg);
		return -1;
	}
	*value=db;
	printf("create_user_table success\n");
	return 0;
}
//创建历史记录表
int create_history_table(sqlite3 *db,msg_t buf)
{
	char sql[120]="";
	sprintf(sql,"create table if not exists \"%s\" (English char,Chinese char,time char);",buf.user);
	//定义接收错误信息的指针
	char *errmsg=NULL;
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
		sqlite3_free(errmsg);
		return -1;
	}
	printf("create_history_table success\n");
	return 0;
}
//创建单词表
int create_word_table(sqlite3 **value)
{
	sqlite3 *db=*value;
	char sql[]="create table if not exists Word_t(word char,meaning char);";
	//定义接收错误信息的指针
	char *errmsg=NULL;
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
		sqlite3_free(errmsg);
		return -1;
	}
	*value=db;
	printf("create_word_table success\n");
	return 0;
}
//删除单词表
int drop_word_table(sqlite3 **value)
{
	sqlite3 *db=*value;
	char sql[]="drop table Word_t;";
	//定义接收错误信息的指针
	char *errmsg=NULL;
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
		sqlite3_free(errmsg);
		return -1;
	}
	*value=db;
	printf("drop_word_table success\n");
	return 0;
}
//关闭数据库
int close_dictionary_db(sqlite3 **db)
{
	if(sqlite3_close(*db)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_close error:%s\n",__LINE__,sqlite3_errmsg(*db));
		return -1;
	}
	printf("sqlite3_close success\n");
	return 0;
}
//定义查找历史记录
int do_search_history(sqlite3 **value,msg_t buf,int newfd,char *user)
{
	sqlite3 *db=*value;
	if(buf.code=='S')
	{
		//准备sql语句
		char sql[128]="";
		sprintf(sql,"select * from \"%s\" ;",user);
		char **res; //接收表结果
		int rows; //行号
		int cols; //列号
		char *errmsg=NULL;//错误信息
		//调用函数,获取sql语句后的结果
		if(sqlite3_get_table(db,sql,&res,&rows,&cols,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"sqlite3_exec error:%s\n",sqlite3_errmsg(db));
			sqlite3_free(errmsg);
			return -1;
		}
		for(int i=1;i<rows+1;i++) //外行
		{
			for(int j=0;j<cols;j++)
			{
				bzero(buf.msg,sizeof(buf.msg));
				sprintf(buf.msg,"%s",res[i*cols+j]);
				if(send(newfd,buf.msg,sizeof(buf.msg),0)<0)
				{
					ERR_MSG("send");
				}
			}
		}
		if(send(newfd,"Q",1,0)<0)
		{
			ERR_MSG("send");
		}
		//将表释放
		sqlite3_free_table(res);
		res=NULL;
	}
	return 0;
}

//定义查找用户
int do_search_user(sqlite3 *db,msg_t buf)
{
	int flag=0;
	if(buf.code=='E'||buf.code=='L')
	{
		//准备sql语句
		char sql[]="select * from User_t;";
		char **res; //接收表结果
		int rows; //行号
		int cols; //列号
		char *errmsg=NULL;//错误信息
		//调用函数,获取sql语句后的结果
		if(sqlite3_get_table(db,sql,&res,&rows,&cols,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"sqlite3_exec error:%s\n",sqlite3_errmsg(db));
			sqlite3_free(errmsg);
			return -1;
		}
		for(int i=1;i<rows+1;i++) //外行
		{
			for(int j=0;j<cols;j+=2)
			{
				if(strcmp(buf.user,res[i*cols+j])==0)
				{
					//1:用户名已注册
					flag=1;
				}			
			}
		}
		//将表释放
		sqlite3_free_table(res);
		res=NULL;
	}
	return flag;
}
//定义查找密码
int do_search_pass(sqlite3 *db,msg_t buf)
{
	int flag=0;
	if(buf.code=='L')
	{
		//准备sql语句
		char sql[]="select * from User_t;";
		char **res; //接收表结果
		int rows; //行号
		int cols; //列号
		char *errmsg=NULL;//错误信息
		//调用函数,获取sql语句后的结果
		if(sqlite3_get_table(db,sql,&res,&rows,&cols,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"sqlite3_exec error:%s\n",sqlite3_errmsg(db));
			sqlite3_free(errmsg);
			return -1;
		}
		for(int i=1;i<rows+1;i++) //外行
		{
			for(int j=1;j<cols;j+=2)
			{
				if(strcmp(buf.passwd,res[i*cols+j])==0)
				{
					//1:密码正确
					flag=1;
				}
			}
		}
		//将表释放
		sqlite3_free_table(res);
		res=NULL;
	}
	return flag;
}
//定义查找单词功能
void do_search_word(sqlite3 **value,msg_t buf,char *user,int newfd)
{
	sqlite3 *db = *value;
	if(buf.code=='F')
	{
		//准备sql语句
		char sql[]="select * from Word_t;";
		char **res; //接收表结果
		int rows; //行号
		int cols; //列号
		char *errmsg=NULL;//错误信息
		//调用函数,获取sql语句后的结果
		if(sqlite3_get_table(db,sql,&res,&rows,&cols,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"sqlite3_exec error:%s\n",sqlite3_errmsg(db));
			sqlite3_free(errmsg);
		}
		for(int i=1;i<rows+1;i++) //外行
		{
			for(int j=0;j<cols;j+=2)
			{
				if(strcmp(buf.msg,res[i*cols+j])==0)
				{
					strcpy(buf.msg,res[i*cols+j+1]);
					printf("%d\n",__LINE__);
					puts(user);
					do_add_history(db,user,res[i*cols+j],res[i*cols+j+1]);
					if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
					{
						ERR_MSG("send");
					}
					sqlite3_free_table(res);
					res=NULL;
					return;
				}
			}
		}
		bzero(buf.msg,sizeof(buf.msg));
		strcpy(buf.msg,"word unexist");
		if(send(newfd,buf.msg,sizeof(buf.msg),0)==-1)
		{
			ERR_MSG("send");
		}
		//将表释放
		sqlite3_free_table(res);
		res=NULL;
	}
	return;
}

//添加用户信息
int do_add_user(sqlite3 *db,msg_t buf)
{
	//准备sql语句
	char sql[128] = "insert into User_t values(user,passwd)";
	//功能:将格式串转换为字符串
	sprintf( sql,"insert into User_t values(\"%s\",\"%s\");",buf.user,buf.passwd);
	//定义接收错误信息的指针
	char *errmsg=NULL;
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
		sqlite3_free(errmsg);
		return -1;
	}
	printf("insert success\n");
	return 0;
}
//添加历史信息
int do_add_history(sqlite3 *db,char *user,char *English,char *Chinese)
{
	//获取查询时间
	time_t t=time(NULL);
	struct tm* info=localtime(&t);
	char p[128]="";
	sprintf(p,"[%4d-%2d-%2d --- %2d:%2d:%2d]",info->tm_year+1900,info->tm_mon+1,\
			info->tm_mday,info->tm_hour,info->tm_min,info->tm_sec);
	//准备sql语句
	char sql[128] = "";
	//功能:将格式串转换为字符串
	sprintf(sql,"insert into \"%s\" values(\"%s\",\"%s\",\"%s\");",user,English,Chinese,p);
	printf("sql = %s\n", sql);//******************
	//定义接收错误信息的指针
	char *errmsg=NULL;
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
		sqlite3_free(errmsg);
		return -1;
	}	
	printf("insert success\n");
	return 0;
}
//添加单词信息
int do_add_word(sqlite3 **value)
{
	sqlite3 *db=*value;
	char word[128]="",meaning[128]="";
	FILE* fp=fopen("./dict.txt","r");
	if(NULL==fp)
	{
		perror("fopen");
		return -1;
	}
	while(1)
	{
		bzero(word,sizeof(word));
		bzero(word,sizeof(meaning));
		if(fscanf(fp,"%s",word)==EOF)
		{
			printf("已读完\n");
			break;
		}
		fgets(meaning,sizeof(meaning),fp);
		meaning[strlen(meaning)-1]=0;
				//准备sql语句
		char sql[128] = "insert into Word_t values(user,passwd)";

		sprintf( sql,"insert into Word_t values(\"%s\",\"%s\");",word,meaning);
		printf("sql = %s\n", sql);
		//定义接收错误信息的指针
		char *errmsg=NULL;
		if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"%d:sqlite3_exec error:%s\n",__LINE__,sqlite3_errmsg(db));
			sqlite3_free(errmsg);
			return -1;
		}
	}
	*value=db;
	printf("insert success\n");
	fclose(fp);
	return 0;
}
int main(int argc, const char *argv[])
{
	//从终端输入地址 端口
	if(3!=argc)
	{
		printf("input error\n");
		printf("error: %s <IP><PORT>\n",argv[0]);
		return -1;
	}
	//定义句柄指针
	sqlite3 *db=NULL;
	//调用创建数据库函数
	create_dictionary_db(&db);
	//创建用户表
	create_user_table(&db);
	//创建单词表
	create_word_table(&db);
	//添加单词信息
	do_add_word(&db);//********************
	//创建套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd==-1)
	{
		ERR_MSG("socket");
	}
	printf("socket success\n");
	//设置端口号快速重用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
	{
		perror("setsockopt error");
		return -1;
	}
	printf("端口快速重用成功\n");
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(atoi(argv[2]));
	sin.sin_addr.s_addr=inet_addr(argv[1]);
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		ERR_MSG("bind");
	}
	printf("bind success\n");
	if(listen(sfd,128)==-1)
	{
		ERR_MSG("listen");
	}
	printf("listen success\n");
	struct sockaddr_in cin;
	cin.sin_family=AF_INET;
	socklen_t socklen=sizeof(cin);
	//定义线程号
	pthread_t tid;
	while(1)
	{
		int newfd=accept(sfd,(struct sockaddr*)&cin,&socklen);
		if(newfd==-1)
		{
			ERR_MSG("accept");
		}
		printf("新客户端连接,newfd=%d\n",newfd);
		//定义传参
		struct cli_msg info;
		info.newfd =newfd;
		info.cin=cin;
		info.db=&db;
		if(pthread_create(&tid,NULL,deal_cli_msg,&info)!=0)
		{
			printf("pthread_create error\n");
			return -1;
		}
		pthread_detach(tid);
	}
	//删除单词表
	drop_word_table(&db);
	//关闭数据库
	close_dictionary_db(&db);
	close(sfd);
	return 0;
} 

 cli.c

#include <head.h>
struct ser_msg
{
    int cfd;
    struct sockaddr_in cin;
};
typedef struct MSG
{
	char code;//L:登录,E:注册,F:查询
	char user[9];
	char passwd[9];
	char msg[128];
}msg_t;
void input(msg_t *buf)
{
	printf("&buf1=%p\n",&buf);
	printf("请输入用户名:");
	bzero(&buf->user,sizeof(buf->user));
	scanf("%s",buf->user);
	getchar();
	printf("请输入密码:");
	bzero(&buf->passwd,sizeof(buf->passwd));
	scanf("%s",buf->passwd);
	printf("%s\t %s \n",buf->user,buf->passwd);
	return;
}
int main(int argc, const char *argv[])
{
	if(3!=argc)
	{
		printf("input error\n");
		printf("error: %s <IP><PORT>\n",argv[0]);
		return -1;
	}
	int cfd = socket(AF_INET,SOCK_STREAM,0);
	if(cfd==1)
	{
		ERR_MSG("socket");
	}
	printf("cfd = %d\n",cfd);
	int reuse =1 ;
	if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
	{
		ERR_MSG("setsockopt");
	}
	struct sockaddr_in cin;
	cin.sin_family = AF_INET;
	cin.sin_port = htons(atoi(argv[2]));
	cin.sin_addr.s_addr = inet_addr(argv[1]);
	if(connect(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1)
	{
		ERR_MSG("connect");
	}
	printf("connect success\n");
	int type=0;
	msg_t buf;
	while(1)
	{	
		system("clear");
		printf("****************\n");
		printf("*****1.注册*****\n");
		printf("*****2.登录*****\n");
		printf("*****3.退出*****\n");
		printf("****************\n");

		printf("输入选项:");
		scanf("%d",&type);
		bzero(buf.msg,sizeof(buf.msg));
		fgets(buf.msg,sizeof(buf.msg),stdin);
		buf.msg[strlen(buf.msg)-1]='\0';
		if(type==1)
		{
			buf.code='E';
			input(&buf);	
			if(send(cfd,&buf,sizeof(buf),0)==-1)
			{
				ERR_MSG("send");
			}
			bzero(&buf,sizeof(buf));
			int res = recv(cfd,&buf.msg,sizeof(buf.msg),0);
			if(res==-1)
			{
				ERR_MSG("recv");
			}
			else if(res==0)
			{
				printf("服务器已经下线\n");
				break;
			}
			printf("server:%s\n",buf.msg);
			if(strcmp(buf.msg,"register success")==0)
			{
				printf("注册成功,请重新登录\n");
				continue;
			}
			else
			{
				printf("注册失败,请重新注册\n");
				continue;
			}
		}
		else if(type==2)
		{
			buf.code='L';
			input(&buf);	
			printf("&buf2=%p\n",&buf);
			printf("buf.user=%s\n",buf.user);
			if(send(cfd,&buf,sizeof(buf),0)==-1)
			{
				ERR_MSG("send");
			}
			bzero(&buf,sizeof(buf));
			int res = recv(cfd,&buf.msg,sizeof(buf.msg),0);
			if(res==-1)
			{
				ERR_MSG("recv");
			}
			else if(res==0)
			{
				printf("服务器已经下线\n");
				break;
			}
			printf("server:%s\n",buf.msg);
			if(strcmp(buf.msg,"login success")==0)
			{
				while(1)
				{
					system("clear");
					printf("****************\n");
					printf("*****1.查找*****\n");
					printf("***2.历史记录***\n");
					printf("*****3.退出*****\n");
					printf("****************\n");
					int num=0;
					printf("请输入选项:");
					scanf("%d",&num);
					if(num==1)
					{
						bzero(buf.msg,sizeof(buf.msg));
						buf.code='F';
						printf("请输入要找到单词:");
						scanf("%s",buf.msg);
						if(send(cfd,&buf,sizeof(buf),0)==-1)
						{
							ERR_MSG("send");
						}
						bzero(&buf,sizeof(buf));
						int res = recv(cfd,&buf.msg,sizeof(buf.msg),0);
						if(res==-1)
						{
							ERR_MSG("recv");
						}
						else if(res==0)
						{
							printf("服务器已经下线\n");
							break;
						}
						if(strcmp(buf.msg,"word unexist")==0)
						{
							printf("单词不存在\n");
							continue;
						}
						printf("意思是:%s\n",buf.msg);
					}
					else if(num==2)
					{
						int i=0;
						bzero(buf.msg,sizeof(buf.msg));
						buf.code='S';
						if(send(cfd,&buf,sizeof(buf),0)==-1)
						{
							ERR_MSG("send");
						}
						printf("历史记录:\n");
						while(1)
						{
							bzero(&buf.msg,sizeof(buf.msg));
							int res = recv(cfd,&buf.msg,sizeof(buf.msg),0);
							if(res==-1)
							{
								ERR_MSG("recv");
							}
							if(res==0)
							{
								printf("服务器已经下线\n");
								break;
							}
							printf("%s  ",buf.msg);
							++i;
							if(i%3==0)
							{
								puts("");
							}
							if(strcmp(buf.msg,"Q")==0)
							break;
						}
					}
					else if (num==3)
					{
						bzero(&buf,sizeof(buf));
						buf.code='Q';
						if(send(cfd,&buf,sizeof(buf),0)==-1)
						{
							ERR_MSG("send");
						}
						close(cfd);
						return 0;
					}
				}
			}
			else
			{
				continue;
			}
			//break;
		}
		else if(type==3)
		{
			bzero(&buf,sizeof(buf));
			buf.code='Q';
			if(send(cfd,&buf,sizeof(buf),0)==-1)
			{
				ERR_MSG("send");
			}
			close(cfd);
			return 0;
		}
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值