电子字典项目

服务器端:

Ser.h

#ifndef __SER_H__
#define __SER_H__

#include <myhead.h>

#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__:",__LINE__);\
	perror(msg);\
}while(0)

//用于客户端与服务器传递消息的结构体
typedef struct {
    char type; 	//协议
    char username[20];
    char password[20];
	char text[128];
}MSG;

#define PORT 8888 	//端口号
#define IP "127.0.0.1" 	//本地主机地址

//响应信号函数
void handler(int sig);
//将dict.txt导入到数据库中
int dicttosql();
//接收信息函数
int do_recv(int newfd);
//注册函数
int do_register(int newfd,sqlite3* db,MSG msg);
//登录函数
int do_login(int newfd,sqlite3* db,MSG msg);
//查询函数
int do_select(int newfd,sqlite3* db,MSG msg);
//历史记录函数
int do_history(int newfd,sqlite3* db,MSG msg);
//退出登录函数
int do_exit(sqlite3* db,MSG msg);

#endif

Ser.c

#include "Ser.h"

//响应信号函数
void handler(int sig){
	while(waitpid(-1,NULL,WNOHANG)>0);
}
//将dict.txt导入到数据库中
int dicttosql()
{
    //以只读的方式打开dict.txt文件
    FILE* fd;
    if((fd=fopen("./dict.txt","r")) == NULL){
        ERR_MSG("open");
        return -1;
    }

    //打开数据库
    sqlite3* db=NULL;
    if(sqlite3_open("./my.db", &db) != 0){
        fprintf(stderr,"__%d__sqlite3_open: %s",\
                __LINE__, sqlite3_errmsg(db));
        return -1;
    }

    //创建数据表dict
    char sql[128]="";
	sprintf(sql, "create table if not exists dict(word char,mean char);");
    char *errmsg = NULL;
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != 0){
        fprintf(stderr, "__%d__create:%s\n",\
                __LINE__,errmsg);
        return -1;
    }
    //创建数据表user
	sprintf(sql, "create table if not exists user(username char primary key,password char,flag char);");
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != 0){
        fprintf(stderr, "__%d__create:%s\n",\
                __LINE__,errmsg);
        return -1;
    }


    char buf[128]="";
    char word[64]="";
    char mean[64]="";     

    while(fgets(buf,128,fd) != NULL){
        buf[strlen(buf)-1]=0;
        for(int i=0;i<strlen(buf);i++){
            if(buf[i]!=' ' && buf[i+1]==' ' && buf[i+2]==' '){
                strncpy(word,buf,i+1);
            }
            if(buf[i]==' ' && buf[i+1]==' ' && buf[i+2]!=' '){
                strcpy(mean,buf+i+2);
            }
        }

        //将word,mean插入到数据库中
        char sql[128]="";
        sprintf(sql,"insert into dict values(\"%s\",\"%s\");", word, mean);
        char *errmsg = NULL;
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) !=0){
            fprintf(stderr, "__%d__insert:%s\n",\
                    __LINE__,errmsg);
            return -1;
        }

        //清空buf,word,mean
        bzero(buf,128);
        bzero(word,64);
        bzero(mean,64);
    }
    printf("导入成功\n");

	//关闭文件
	fclose(fd);

	//关闭数据库
	sqlite3_close(db);
	return 0;
}

int do_recv(int newfd){
	MSG msg;

	//打开数据库
	sqlite3* db=NULL;
	if(sqlite3_open("./my.db", &db) != 0){
		fprintf(stderr,"__%d__sqlite3_open: %s",__LINE__, sqlite3_errmsg(db));
		return -1;
	}

	int flag=0;
	while(1){
		if(-1 == recv(newfd,&msg,sizeof(msg),0)){
			ERR_MSG("recv");
			return -1;
		}
		switch(msg.type){
		case 'R':
			//注册函数
			do_register(newfd,db,msg);
			break;
		case 'L':
			//登录函数
			do_login(newfd,db,msg);
			break;
		case 'S':
			//查询函数
			do_select(newfd,db,msg);
			break;
		case 'H':
			//历史记录函数
			do_history(newfd,db,msg);
			break;
		case 'E':
			//退出登录函数
			do_exit(db,msg);
			break;
		case 'Q':
			flag=1;
		}
		if(flag==1){
			break;
		}
	}
	//关闭数据库
	sqlite3_close(db);
	return 0;

}

int do_register(int newfd,sqlite3* db,MSG msg){
	char sql[128]="";
	sprintf(sql,"insert into user values(\"%s\",\"%s\",\"%c\");",msg.username,msg.password,'N');
	//将用户信息添加到表中
	char* errmsg = NULL;
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		//判断用户是否已经在表中了
		if(sqlite3_errcode(db) == 19)
		{
			printf("用户名[%s]请勿重复注册\n",msg.username);
			//重复注册
			msg.type='F';
			strcpy(msg.text,"用户名重复");
			//发送给客户端
			if(send(newfd,&msg,sizeof(msg),0) < 0)
			{
				ERR_MSG("send");
				return -1;
			}
			return -1;
		}
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);		
	}	
	msg.type='T';
	//创建一张历史记录表
	sprintf(sql,"create table if not exists %s (word char,mean char,time char);",msg.username);	

	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
		return -1;
	}
	printf("用户名[%s]注册成功\n",msg.username);

	strcpy(msg.text,"注册成功");
	//发送给客户端
	if(send(newfd,&msg,sizeof(msg),0) < 0)
	{
		ERR_MSG("send");
		return -1;
	}
	return 0;

}

int do_login(int newfd,sqlite3* db,MSG msg){
	char sql[128]="";
	char **pres=NULL;
	int row,column;
	//查询是否是用户名输入错误
	sprintf(sql,"select * from user where username=\"%s\";",msg.username);
	char* errmsg = NULL;
	if(sqlite3_get_table(db, sql, &pres, &row,&column, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
		return -1;
	}	
	if(0==row){
		printf("[%s]用户名输入错误\n",msg.username);
		msg.type = 'F';
		strcpy(msg.text,"用户名输入错误");
	}
	else{
		sqlite3_free_table(pres);
		//查询是否是密码输入错误
		sprintf(sql,"select * from user where username=\"%s\" and password=\"%s\";",msg.username,msg.password);
		char* errmsg = NULL;
		if(sqlite3_get_table(db, sql, &pres, &row,&column, &errmsg) != SQLITE_OK)
		{
			fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
			return -1;
		}	
		if(0==row){
			printf("[%s]密码输入错误\n",msg.username);
			msg.type = 'F';
			strcpy(msg.text,"密码输入错误");
		}
		else{
			sqlite3_free_table(pres);
			//查询用户是否已经在线
			sprintf(sql,"select * from user where username=\"%s\" and password=\"%s\" and flag=\"%c\";",msg.username,msg.password,'N');
			char* errmsg = NULL;
			if(sqlite3_get_table(db, sql, &pres, &row,&column, &errmsg) != SQLITE_OK)
			{
				fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
				return -1;
			}	
			if(0==row){
				printf("[%s]用户在线\n",msg.username);
				msg.type = 'F';
				strcpy(msg.text,"用户已在线");
			}
			else{
				//登录成功
				msg.type = 'T';
				printf("[%s]登录成功\n",msg.username);
				strcpy(msg.text,"登录成功");
				//将用户上线信息存入数据库
				sprintf(sql,"update user set flag=\"%c\" where username=\"%s\";",'Y',msg.username);
				if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK){
					fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
					return -1;

				}			
			}
		}
	}
	//发送给客户端
	if(send(newfd,&msg,sizeof(msg),0) < 0)
	{
		ERR_MSG("send");
		return -1;
	}
	sqlite3_free_table(pres);

	return 0;
}

int do_select(int newfd,sqlite3* db,MSG msg){
	char sql[256]="";
	char **pres=NULL;
	int row,column;
	//查询dict表中用户查的单词的意思
	sprintf(sql,"select * from dict where word=\"%s\";",msg.text);
	char* errmsg = NULL;
	
	if(sqlite3_get_table(db, sql, &pres, &row,&column, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
		return -1;
	}
	printf("[%s]查询成功\n",msg.username);
	//将查到的单词和意思发给用户
	sprintf(msg.text,"%s\t%s",pres[2],pres[3]);
	if(-1 == send(newfd,&msg,sizeof(msg),0)){
		ERR_MSG("send");
		return -1;
	}


	//将查到的单词和意思和当时的时间存入历史记录表中
	char ti[30] = "";
	time_t t = time(NULL);
	struct tm *info = NULL;
	info = localtime(&t);
	sprintf(ti,"%d-%02d-%02d %02d:%02d:%02d",info->tm_year+1900, info->tm_mon+1, info->tm_mday,info->tm_hour, info->tm_min, info->tm_sec);
	
	sprintf(sql,"insert into \"%s\" values(\"%s\",\"%s\",\"%s\");",msg.username,pres[2],pres[3],ti);	

	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
		return -1;
	}

	sqlite3_free_table(pres);
	return 0;
}

int do_history(int newfd,sqlite3* db,MSG msg){
	char sql[256]="";
	char buf[128]="";
	char **pres=NULL;
	int row,column;
	//查询用用户的用户名创出的表中的所有记录
	sprintf(sql,"select * from \"%s\";",msg.username);
	char* errmsg = NULL;

	if(sqlite3_get_table(db, sql, &pres, &row,&column, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
		return -1;
	}
	bzero(msg.text,sizeof(msg.text));
	//将查到的单词和意思和当时的时间拼在一起发给客户端
    for(int i=0; i<(row+1)*column; i+=3)
	{
		sprintf(buf,"%s\t%s\t%s\n",pres[i],pres[i+1],pres[i+2]);	
		strcat(msg.text,buf);
	}
	
	if(send(newfd,&msg,sizeof(msg),0) < 0)
	{
		ERR_MSG("send");
		return -1;
	}
	printf("[%s]的历史记录查询成功\n",msg.username);

    sqlite3_free_table(pres);
    return 0;

}

int do_exit(sqlite3* db,MSG msg){
	char sql[128]="";
	char *errmsg=NULL;
	//将用户下线信息存入数据库
	sprintf(sql,"update user set flag=\"%c\" where username=\"%s\";",'N',msg.username);
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK){
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
		return -1;
	}	
	printf("[%s]已下线\n",msg.username);
	return 0;
}

server.c

#include "Ser.h"

int main(int argc, const char *argv[])
{
	//用信号回收僵尸进程
	if(signal(SIGCHLD,handler)==SIG_ERR){
		ERR_MSG("signal");
		return -1;
	}
	
	//如果没有导入dict.txt,先导入
	printf("检查字典是否已经导入数据库...\n");
	sleep(1);
	if(!access("my.db",F_OK)){
		printf("已导入数据库\n");
	}
	else{
		printf("未导入,正在导入中...\n");
		dicttosql();
	}
	
	//创建流式套接字:socket
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(-1 == sfd){
		ERR_MSG("socket");
		return -1;
	}

	//服务器信息地址结构体
	struct sockaddr_in sin;
	sin.sin_family      = AF_INET;
	sin.sin_port        = htons(PORT);      //服务器PORT
	sin.sin_addr.s_addr = inet_addr(IP);    //服务器IP  

	//绑定服务器IP和端口号:bind
	if(-1 == bind(sfd,(struct sockaddr*)&sin,sizeof(sin))){
		ERR_MSG("bind");
		return -1;
	}

	//将套接字转化为被动监听状态:listen
	if(-1 == listen(sfd,128)){
		ERR_MSG("listen");
		return -1;
	}

	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);
	MSG msg;

	while(1){
		//获取一个已经完成的客户端信息,生成一个新的文件描述符:accept
		int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
		if(-1 == newfd){
			ERR_MSG("accept");
			return -1;
		}

		//创建进程
		pid_t pid=fork();
		if(0 == pid){
			close(sfd);
			//子进程接收从客户端发来的数据,并做处理
			do_recv(newfd);
			exit(0);
		}
		close(newfd);
	}
	close(sfd);
	return 0;
}

客户端:

Cli.h

#ifndef __CLI_C__
#define __CLI_C__

#include <myhead.h>                        
                                           
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__:",__LINE__);\
    perror(msg);\
}while(0)                                  
         
//用于客户端与服务器传输的结构体
typedef struct {                           
    char type;   //协议                          
    char username[20];                     
    char password[20];  
	char text[128];
}MSG;                                      
                                           
#define PORT 8888 	//端口号
#define IP "127.0.0.1" 	//本地主机地址

//注册函数
int do_register(int cfd);
//登录函数
int do_login(int cfd);
//查询函数
int do_select(int cfd,char *name);
//历史记录函数
int do_history(int cfd,char *name);
//退出登录函数
int do_exit(int cfd,char *name);
//退出函数
int do_quit(int cfd);


#endif

Cli.c

#include "Cli.h"
//注册函数
int do_register(int cfd){
	MSG msg;
	msg.type='R';

	printf("请输入用户名>>>");
	fgets(msg.username,sizeof(msg.username),stdin); 	//终端输入用户名
	msg.username[strlen(msg.username)-1] = 0;

	printf("请输入密码>>>");
	fgets(msg.password,sizeof(msg.password),stdin); 	//终端输入密码
	msg.password[strlen(msg.password)-1] = 0;

    if(-1 == send(cfd,&msg,sizeof(msg),0)){
		ERR_MSG("send");
		return -1;
	}
	if(-1 == recv(cfd,&msg,sizeof(msg),0))
	{
		ERR_MSG("recv");
		return -1;
	}

	if(msg.type == 'T')   //注册成功
	{
		printf("%s\n",msg.text);
	}
	else if(msg.type == 'F')   //注册失败
	{
		printf("%s\n",msg.text);
	}
	return 0;
}
//登录函数
int do_login(int cfd){
	int flag=1; 	//用于判断退出登录的标示
	MSG msg;
	msg.type='L';

	printf("请输入用户名>>>");
	fgets(msg.username,sizeof(msg.username),stdin); 	//终端输入用户名
	msg.username[strlen(msg.username)-1] = 0;

	printf("请输入密码>>>");
	fgets(msg.password,sizeof(msg.password),stdin); 	//终端输入密码
	msg.password[strlen(msg.password)-1] = 0;

	if(-1 == send(cfd,&msg,sizeof(msg),0)){
		ERR_MSG("send");
		return -1;
	}
	if(-1 == recv(cfd,&msg,sizeof(msg),0))
	{
		ERR_MSG("recv");
		return -1;
	}
	printf("%s\n",msg.text);
	if(msg.type == 'F')   //登录失败
	{
		return -1;
	}
	while(1){
		system("clear");
		printf("**********************\n");
		printf("********1.查询********\n");
		printf("******2.历史记录******\n");
		printf("******3.退出登录******\n");
		printf("**********************\n");

		int choose2;
		printf("请选择>>>");
		scanf("%d",&choose2);
		while(getchar()!=10);

		switch(choose2){
		case 1:
			do_select(cfd,msg.username);
			break;
		case 2:
			do_history(cfd,msg.username);
			break;	
		case 3:
			flag=do_exit(cfd,msg.username);
			break;
		default:
			printf("输入有误,请重新输入\n");
		}
		if(flag==0)
		{
			break;
		}
		printf("任意字符清屏>>>");
		while(getchar()!=10);
	}

	return 0;
}
//查询函数
int do_select(int cfd,char *name){
	MSG msg;
	msg.type='S';

	strcpy(msg.username,name);

	while(1){
		printf("请输入要翻译的词(输入Q结束查询)>>>");

		fgets(msg.text,sizeof(msg.text),stdin);
		msg.text[strlen(msg.text)-1] = 0;

		if(!strcmp(msg.text,"Q"))//退出查询
		{
			break;
		}
		if(-1 == send(cfd,&msg,sizeof(msg),0)){
			ERR_MSG("send");
			return -1;
		}
		if(-1 == recv(cfd,&msg,sizeof(msg),0))
		{
			ERR_MSG("recv");
			return -1;
		}
		printf("%s\n",msg.text);
	}
	return 0;
}
//历史记录函数
int do_history(int cfd,char *name){
	MSG msg;
	msg.type='H';

	strcpy(msg.username,name);

	if(-1 == send(cfd,&msg,sizeof(msg),0)){
		ERR_MSG("send");
		return -1;
	}
	if(recv(cfd,&msg,sizeof(msg),0) < 0)
	{
		ERR_MSG("recv");
		return -1;
	}
	printf("%s",msg.text);
	return 0;
}
//退出登录函数
int do_exit(int cfd,char *name){
	MSG msg;
	msg.type='E';

	strcpy(msg.username,name);

	if(-1 == send(cfd,&msg,sizeof(msg),0)){
		ERR_MSG("send");
		return -1;
	}
	return 0;
}
//退出函数
int do_quit(int cfd){
	MSG msg;
	msg.type='Q';
	if(-1 == send(cfd,&msg,sizeof(msg),0)){
		ERR_MSG("send");
		return -1;
	}
	return 0;
}

client.c

#include "Cli.h"

int main(int argc, const char *argv[])
{
	//创建流式套接字:socket
	int cfd=socket(AF_INET,SOCK_STREAM,0);
	if(-1 == cfd){
		ERR_MSG("socket");
		return -1;
	}

	//服务器信息地址结构体
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(PORT); 		//服务器PORT
	sin.sin_addr.s_addr = inet_addr(IP); 	//服务器IP
	
	//与服务器建立连接:connect
	if(-1 == connect(cfd,(struct sockaddr*)&sin,sizeof(sin))){
		ERR_MSG("connect");
		return -1;
	}

	int choose=0;
	int flag=0;
	while(1){
		system("clear");
		printf("**********************\n");
		printf("********1.注册********\n");
		printf("********2.登录********\n");
		printf("********3.退出********\n");
		printf("**********************\n");

		printf("请选择>>>");
		scanf("%d",&choose);
		while(getchar()!=10);
		switch(choose){
		case 1:
			do_register(cfd);
			break;
		case 2:
			do_login(cfd);
			break;
		case 3:
			flag=1;
			do_quit(cfd);
			break;
		default:
			printf("输入有误,请重新输入\n");
		}
		if(flag==1){
			break;
		}
		printf("任意字符清屏>>>");
		while(getchar()!=10);
	}

	//关闭套接字文件描述符
	close(cfd);

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值