2022.12.1--电子词典项目(已完成)

项目要求:
1.登录注册功能,不能重复登录,重复注册
2.单词查询功能
3.历史记录功能,存储单词,意思,以及查询时间
4.基于 TCP ,支持多客户端连接
5.采用数据库保存用户信息与历史记录
6.将 dict . txt 的数据导入到到数据库中保存。
7.按下 ctrl + c 退出客户端后,注销该客户端的登录信息
格式要求:
1, main 函数只跑逻辑,不允许胞功能能代码
2,功能代码封装成函数

流程图

代码

//头文件
#ifndef __INET_H__
#define __INET_H__


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

#define ERR(msg) do{\
	fprintf(stderr,"%d--",__LINE__);\
	perror(msg);\
}while(0)


#endif
//服务器
#include "inet.h"
#define SER_IP "192.168.8.205"
#define SER_PORT 7777
#define N 128
struct data_type
{
	int nfd;
	struct sockaddr_in cin;
};
//服务器初始化
int ser_init();
//登录功能,并记录下正在登录中的用户
int login(int nfd,char *buf,char *name);
//退出是删除登录的用户
int del_temp_usr(char *name);
//注册功能
int sign_up(int nfd,char *buf);
//查找单词,并记录下查询结果
int find_word(int nfd,char *buf,char *name);
//查看该name的历史记录
int history(int nfd,char *name);
void *task(void *arg)
{
	int nfd=((struct data_type*)arg)->nfd;
	struct sockaddr_in cin=((struct data_type*)arg)->cin;
	//接收客户端登录信息,判断是否是已注册用户
	//回复相应信息给客户端
	char buf[N]="";
	char name[10]="";
	while(1)
	{
		bzero(buf,N);
		ssize_t res_rcv=recv(nfd,buf,N,0);
		if(res_rcv<0)
		{
			ERR("recv");
			return NULL;
		}
		else if(res_rcv==0)
		{
			printf("%d号客户端退出\n",nfd);
			//退出后删除此用户的登录信息
			del_temp_usr(name);
			pthread_exit(NULL);
		}
		switch(buf[0])
		{
		case '1':
			//如果登录功能函数返回值为1则登陆成功
			if(login(nfd,buf,name)==1)
			{
				while(1)
				{
					bzero(buf,N);
					res_rcv=recv(nfd,buf,N,0);
					if(res_rcv<0)
					{
						ERR("recv");
						return NULL;
					}
					else if(res_rcv==0)
					{
						printf("%d号客户端退出\n",nfd);
						//退出后删除此用户的登录信息
						del_temp_usr(name);
						pthread_exit(NULL);
					}
					switch(buf[0])
					{
					case '1':find_word(nfd,buf,name);break;
				 	case '2':history(nfd,name);break;
					case '3':goto END;
					default:break;
					}
				}
			}
			break;
		case '2':sign_up(nfd,buf);break;
		case '3':goto END;
		default:break;
		}
	}
END:
	close(nfd);
	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	int sfd=ser_init();
	printf("服务器就绪\n");
	struct sockaddr_in cin;
	socklen_t addr=sizeof(cin);
	while(1)
	{
		int nfd=accept(sfd,(struct sockaddr*)&cin,&addr);
		if(nfd<0)
		{
			ERR("accept");
			return -1;
		}
		printf("%d号客户端连接成功\n[%s:%d]\n",nfd,\
				inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
		struct data_type info={nfd,cin};
		pthread_t tid;
		if(pthread_create(&tid,NULL,task,(void *)&info)<0)
		{
			ERR("pthread_create");
			return -1;
		}
		pthread_detach(tid);
	}
	close(sfd);
	return 0;
}
int ser_init()
{
	//创建套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR("socket");
		return -1;
	}
	//设置端口允许重用
	int a=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&a,sizeof(a))<0)
	{
		ERR("setsockopt");
		return -1;
	}
	//绑定服务器IP和端口
	struct sockaddr_in sin={AF_INET,htons(SER_PORT),inet_addr(SER_IP)};
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR("bind");
		return -1;
	}
	//设置为被动监听状态
	if(listen(sfd,10)<0)
	{
		ERR("listen");
		return -1;
	}
	return sfd;
}
int login(int nfd,char *buf,char *name)
{
	char passwd[10]="";
	char *p=buf+1;
	int count=0;
	int i=0;
	//获取输入的账户和密码
	while(*p)
	{
		if(*p==' ')
		{
			strcpy(passwd,p+1);
			break;
		}
		name[i++]=*p++;
	}
	//打开数据库
	sqlite3 *db=NULL;
	if(sqlite3_open("./wang.db",&db)!=SQLITE_OK)
	{
		printf("%d--sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	char *msg=NULL;
	//创建一个表记录正在登陆中的用户
	char sql[N]="create table if not exists temp_usr (name char);";
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	char **temp_pres=NULL;
	int temp_row=0;
	int temp_col=0;
	//打开存储已注册的用户信息的表
	strcpy(sql,"create table if not exists usr (name char primary key,passwd char);");
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	char **pres=NULL;
	int row=0;
	int col=0;
	int flag=0;
	strcpy(sql,"select * from usr");
	if(sqlite3_get_table(db,sql,&pres,&row,&col,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	//只遍历用户表里的name信息
	for(int i=0;i<((row+1)*col)/2;i++)
	{
		//先判断输入的name是否是注册过的
		if(strcmp(name,pres[2*i])==0)
		{
			flag=1;
			bzero(buf,N);
			//再判断输入的密码是否正确
			if(strcmp(passwd,pres[2*i+1])==0)
			{
				//然后遍历记录临时登录的用户信息表
				//判断是否是正在登录的用户
				strcpy(sql,"select * from temp_usr");
				if(sqlite3_get_table(db,sql,&temp_pres,&temp_row,&temp_col,&msg)!=SQLITE_OK)
				{
					printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
					return -1;
				}
				for(int j=1;j<((temp_row+1)*temp_col);j++)
				{
					if(strcmp(temp_pres[j],name)==0)
					{
						strcpy(buf,"account logined in");
						if(send(nfd,buf,N,0)<0)
						{
							ERR("send");
							return -1;
						}
						return -1;
					}
				}
				//如果不是正在登陆中的用户则把该用户记录到临时用户表中
				bzero(sql,N);
				sprintf(sql,"insert into temp_usr values ('%s');",name);
				if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
				{
					printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
					return -1;
				}
				//如果不是正在登陆中的用户,则登陆成功
				strcpy(buf,"login success");
				if(send(nfd,buf,N,0)<0)
				{
					ERR("send");
					return -1;
				}
				return 1;
			}
			else
			{
				//密码错误,登录失败
				strcpy(buf,"passwd error");
				if(send(nfd,buf,N,0)<0)
				{
					ERR("send");
					return -1;
				}
				break;
			}
		}
	}
	if(flag==0)
	{
		bzero(buf,N);
		//不是已注册用户
		strcpy(buf,"account not exist");
		if(send(nfd,buf,N,0)<0)
		{
			ERR("send");
			return -1;
		}
	}
	sqlite3_free_table(pres);
	sqlite3_free_table(temp_pres);
	if(sqlite3_close(db)<0)
	{
		printf("%d--sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	return 0;
}
int del_temp_usr(char *name)
{
	sqlite3 *db=NULL;
	if(sqlite3_open("./wang.db",&db)!=SQLITE_OK)
	{
		printf("%d--sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	char *msg=NULL;
	char sql[N]="create table if not exists temp_usr (name char);";
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	bzero(sql,N);
	sprintf(sql,"delete from temp_usr where name='%s';",name);
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	if(sqlite3_close(db)<0)
	{
		printf("%d--sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	return 0;
}
int sign_up(int nfd,char *buf)
{	
	char name[10]="";
	char passwd[10]="";
	char *p=buf+1;
	int i=0;
	//获取输入的账户和密码
	while(*p)
	{
		if(*p==' ')
		{
			strcpy(passwd,p+1);
			break;
		}
		name[i++]=*p++;
	}
	//打开数据库
	sqlite3 *db=NULL;
	if(sqlite3_open("./wang.db",&db)!=SQLITE_OK)
	{
		printf("%d--sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	char *msg=NULL;
	char sql[N]="create table if not exists usr (name char primary key,passwd char);";
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	char **pres=NULL;
	int row=0;
	int col=0;
	int flag=0;
	bzero(sql,N);
	
	strcpy(sql,"select * from usr");
	if(sqlite3_get_table(db,sql,&pres,&row,&col,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	//只遍历用户表里的name信息
	for(int i=0;i<((row+1)*col)/2;i++)
	{
		//如果已存在则不注册
		if(strcmp(name,pres[2*i])==0)
		{
			bzero(buf,N);
			strcpy(buf,"account already exists");
			if(send(nfd,buf,N,0)<0)
			{
				ERR("send");
				return -1;
			}
			return -1;
		}
	}
	bzero(sql,N);
	//注册用户信息
	sprintf(sql,"insert into usr values ('%s','%s');",name,passwd);
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	bzero(buf,N);
	strcpy(buf,"sign up success");
	if(send(nfd,buf,N,0)<0)
	{
		ERR("send");
		return -1;
	}
	sqlite3_free_table(pres);
	if(sqlite3_close(db)<0)
	{
		printf("%d--sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	return 0;
}
int find_word(int nfd,char *buf,char *name)
{
	//打开数据库
	sqlite3 *db=NULL;
	if(sqlite3_open("./wang.db",&db)!=SQLITE_OK)
	{
		printf("%d--sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	char *msg=NULL;
	char sql[N]="create table if not exists dict (word char,meaning char);";
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	//查询词典表
	char **pres=NULL;
	int row=0;
	int col=0;
	int flag=0;
	bzero(sql,N);
	sprintf(sql,"select * from dict where word='%s';",buf+1);
	if(sqlite3_get_table(db,sql,&pres,&row,&col,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	char err_word[N]="";
	strcpy(err_word,buf+1);
	bzero(buf,N);
	//单词输入错误
	if(row==0)
	{
		sprintf(buf,"[%s]\tword not exist\n",err_word);
	}
	//将查找到的单词及意思存储到buf中
	else
	{
		int k=col;
		for(int i=1;i<row+1;i++)
		{
			for(int j=0;j<col;j++)
			{
				strcat(buf,pres[k++]);
				strcat(buf,"   ");
			}
			strcat(buf,"\n");
		}
	}
	//发给用户查询结果
	if(send(nfd,buf,N,0)<0)
	{
		ERR("send");
		return -1;
	}
	//创建一个表记录该用户的查询记录
	strcpy(sql,"create table if not exists history (name char,result char,time char);");
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	//记录查询时间
	time_t t;
	t=time(NULL);
	char find_time[N]="";
	struct tm *tm=localtime(&t);
	sprintf(find_time,"%d-%02d-%02d %02d:%02d:%02d",tm->tm_year+1900,\
			tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
	//将用户名、查询结果、查询时间写入表中
	char buf1[N]="";
	char buf2[N]="";
	char *p=buf;
	int i=0;
	while(*p)
	{
		buf1[i++]=*p++;
		if(*p=='\n')
		{
			bzero(sql,N);
			sprintf(sql,"insert into history values ('%s','%s','%s')",name,buf1,find_time);
			if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
			{
				printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
				return -1;
			}
			if(*(p+1))
			{
				strcpy(buf2,p+1);
				buf2[strlen(buf2)-1]=0;
				bzero(sql,N);
				sprintf(sql,"insert into history values ('%s','%s','%s')",name,buf2,find_time);
				if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
				{
					printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
					return -1;
				}
			}
			break;
		}
	}
	sqlite3_free_table(pres);
	if(sqlite3_close(db)<0)
	{
		printf("%d--sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	return 0;
}
int history(int nfd,char *name)
{
	//打开数据库
	sqlite3 *db=NULL;
	if(sqlite3_open("./wang.db",&db)!=SQLITE_OK)
	{
		printf("%d--sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	char *msg=NULL;
	char sql[N]="create table if not exists history (name char,result char,time char);";
	if(sqlite3_exec(db,sql,NULL,NULL,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	char **pres=NULL;
	int row=0;
	int col=0;
	bzero(sql,N);
	//遍历该用户的历史记录
	sprintf(sql,"select * from history where name='%s';",name);
	if(sqlite3_get_table(db,sql,&pres,&row,&col,&msg)!=SQLITE_OK)
	{
		printf("%d--sqlite3_exec:%s\n",__LINE__,msg);
		return -1;
	}
	char buf[1024]="";
	int k=col;
	for(int i=1;i<row+1;i++)
	{
		for(int j=0;j<col;j++)
		{
			strcat(buf,pres[k++]);
			strcat(buf,"   ");
		}
		strcat(buf,"\n");
	}
	if(send(nfd,buf,1024,0)<0)
	{
		ERR("send");
		return -1;
	}
	sqlite3_free_table(pres);
	if(sqlite3_close(db)<0)
	{
		printf("%d--sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
		return -1;
	}
	return 0;
}
//客户端
#include "inet.h"
#define SER_IP "192.168.8.205"
#define SER_PORT 7777
#define N 128
//客户端初始化
int cli_init();
//登录功能
int login(int sfd,char *msg);
//注册功能
int sign_up(int sfd,char *msg);
//查单词功能
int find_word(int sfd,char *msg);
//查历史记录功能
int history(int sfd,char *msg);
int main(int argc, const char *argv[])
{
	int sfd=cli_init();
	printf("服务器连接成功\n");
	struct sockaddr_in cin;
	socklen_t addr=sizeof(cin);
	char msg[N]="";
	char h_msg[1024]="";
	while(1)
	{
		printf("1---登录\n");
		printf("2---注册\n");
		printf("3---退出\n");
		printf("请输入:");
		char ch=getchar();
		while(getchar()!=10);
		switch(ch)
		{
		case '1':
			login(sfd,msg);
			printf("%s\n",msg);
			//判断接收到的信息是否是登录成功
			if(strcmp(msg,"login success")==0)
			{
				while(1)
				{
					printf("1---查单词\n");
					printf("2---查历史记录\n");
					printf("3---退出\n");
					printf("请输入:");
					ch=getchar();
					while(getchar()!=10);
					switch(ch)
					{
					case '1':
						find_word(sfd,msg);
						printf("%s",msg);
						break;
					case '2':
						history(sfd,h_msg);
						printf("%s",h_msg);
						break;
					case '3':goto END;
					default:printf("输入错误\n");
					}
					printf("输入任意字符清屏:");
					while(getchar()!=10);
					system("clear");
				}
			}
			break;
		case '2':
			sign_up(sfd,msg);
			printf("%s\n",msg);
			break;
		case '3':goto END;
		default:printf("输入错误\n");
		}
		printf("输入任意字符清屏:");
		while(getchar()!=10);
		system("clear");
	}
END:
	close(sfd);
	return 0;
}
int cli_init()
{
	//创建套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR("socket");
		return -1;
	}
	//设置端口允许重用
	int a=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&a,sizeof(a))<0)
	{
		ERR("setsockopt");
		return -1;
	}
	//获取服务器IP和端口
	struct sockaddr_in sin={AF_INET,htons(SER_PORT),inet_addr(SER_IP)};
	//连接服务器
	if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR("connect");
		return -1;
	}
	return sfd;
}
int login(int sfd,char *msg)
{
	char buf[N]="";
	buf[0]='1';
	char name[10]="";
	char passwd[10]="";
	printf("请输入账户:");
	scanf("%s",name);
	while(getchar()!=10);
	printf("请输入密码:");
	scanf("%s",passwd);
	while(getchar()!=10);
	sprintf(buf+1,"%s %s",name,passwd);
	if(send(sfd,buf,N,0)<0)
	{
		ERR("send");
		return -1;
	}
	bzero(msg,N);
	if(recv(sfd,msg,N,0)<0)
	{
		ERR("recv");
		return -1;
	}
	return 0;
}
int sign_up(int sfd,char *msg)
{
	char buf[N]="";
	buf[0]='2';
	char name[10]="";
	char passwd[10]="";
	printf("请输入账户:");
	scanf("%s",name);
	while(getchar()!=10);
	printf("请输入密码:");
	scanf("%s",passwd);
	while(getchar()!=10);
	sprintf(buf+1,"%s %s",name,passwd);
	if(send(sfd,buf,N,0)<0)
	{
		ERR("send");
		return -1;
	}
	bzero(msg,N);
	if(recv(sfd,msg,N,0)<0)
	{
		ERR("recv");
		return -1;
	}
	return 0;
}
int find_word(int sfd,char *msg)
{
	char buf[N]="";
	buf[0]='1';
	char word[20]="";
	printf("请输入要查找的单词:");
	fgets(buf+1,N,stdin);
	buf[strlen(buf)-1]=0;
	if(send(sfd,buf,N,0)<0)
	{
		ERR("send");
		return -1;
	}
	bzero(msg,N);
	if(recv(sfd,msg,N,0)<0)
	{
		ERR("recv");
		return -1;
	}
	return 0;
}
int history(int sfd,char *h_msg)
{
	char buf[N]="";
	buf[0]='2';
	if(send(sfd,buf,N,0)<0)
	{
		ERR("send");
		return -1;
	}
	bzero(h_msg,1024);
	if(recv(sfd,h_msg,1024,0)<0)
	{
		ERR("recv");
		return -1;
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值