电子字典项目

服务器端:

Ser.h

#ifndef __SER_H__
#define __SER_H__

#include 

#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;itm_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                         
                                           
#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;
}

你可能感兴趣的:(数据库,项目)