一、项目要求
- 登录注册功能,不能重复登录,重复注册
- 单词查询功能
- 历史记录功能,存储单词,意思,以及查询时间
- 基于TCP,支持多客户端连接
- 采用数据库保存用户信息与历史记录
- 将dict.txt的数据导入到数据库中保存。
- 按下ctrl+c退出客户端后,注销该客户端的登录信息
二、主要实现功能
- 注册
- 登录
- 查询单词
- 查询历史记录
- 退出登录
三、框架设计
3.1 服务器
3.2 客户端
四、功能实现
4.1 服务器实现功能代码
4.1.1 导入词典
主要流程:
- 创建并打开数据库
- 创建数据表
- 打开词典所在目录文件
- 逐行读取并插入到数据表中
- 关闭文件描述符,关闭数据库
//导入词典
int import_dict(sqlite3 *db)
{
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建一个表
char sql[128] = "create table if not exists dict (word char,mean char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
//打开文件
FILE* fp = fopen("./dict.txt", "r");
if(NULL == fp)
{
perror("fopen");
return -1;
}
//循环读取文件中的数据,一行一行的读取
char buf[256] = "";
char word[32] = "";
char mean[200] = "";
int count = 1;
int i = 0;
char* ptr = NULL;
printf("importing dictionary...\n");
while(1)
{
if(fgets(buf, sizeof(buf), fp) == NULL)
break;
buf[strlen(buf)-1] = 0;
//分离单词和意思
bzero(word, sizeof(word));
bzero(mean, sizeof(mean));
//获取" "子串在buf中的地址
ptr = strstr(buf, " ");
if(NULL == ptr)
{
printf("没有找到对应子串\n");
break;
}
strncpy(word, buf, ptr-buf); //" "子串前面是单词
strcpy(mean, ptr+3); //" "子串后面是意思
//插入到数据库中
sprintf(sql,"insert into dict values (\"%s\", \"%s\");", word, mean);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec failed:%s __%d__\n", errmsg, __LINE__);
return -1;
}
}
//关闭文件
fclose(fp);
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
printf("dictionary import completed...\n");
return 0;
}
4.1.2 注册
主要流程:
- 创建并打开数据库
- 创建数据表
- 匹配来自客户端的用户名,若存在,则回复用户名已存在;若不存在,则将用户名与密码插入数据表中
- 关闭数据库
//匹配用户名是否存在
int do_select_user(sqlite3 *db,char *name)
{
char sql[128] = "select name from user;";
char **pres = NULL;
int row,column;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
for(int i=1;i<(row+1)*column;i++)
{
if(strcmp(pres[i],name) == 0)
{
fprintf(stderr,"sqlite3_exec: name already existss\n");
return 1;
}
}
return 0;
}
//实现注册功能
int Register(sqlite3 *db,char *buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建一个表
char sql[128] = "create table if not exists user (name char,passwd char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char *name = buf+2;
char *passwd = buf+2+strlen(buf+2)+1;
if(do_select_user(db,name) == 1)
{
return 1;
}
sprintf(sql,"insert into user values ('%s','%s');",name,passwd);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
printf("register success...\n");
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 0;
}
4.1.3 登录
主要流程:
- 创建并打开数据库
- 创建数据表
- 匹配来自客户端的用户名和密码,若用户名和密码与数据库中的数据相匹配,则登录成功,否则登录失败
- 关闭数据库
//实现登录功能
int Login(sqlite3 *db,char *buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
char sql[128] = "create table if not exists user (name char,passwd char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
strcpy(sql,"select * from user;");
char **pres = NULL;
int row,column;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char *name = buf+2;
char *passwd = buf+2+strlen(buf+2)+1;
for(int i=2;i<(row+1)*column;i++)
{
if(strcmp(pres[i],name) == 0 && strcmp(pres[i+1],passwd) == 0)
{
printf("login success...\n");
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 2;
}
}
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 3;
}
4.1.4 查找单词
主要流程:
- 创建并打开数据库
- 创建数据表
- 匹配来自客户端的单词,若存在,则返回查询结果并将查询记录插入到数据表中,若不存在,则查询失败
- 关闭数据库
//插入记录
int Insert(sqlite3 *db,char *words,char *mean,char *save_buf)
{
//获取当前时间
time_t t;
struct tm *info=NULL;
char mytime[128] = "";
t = time(NULL);
info = localtime(&t);
sprintf(mytime,"%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);
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建一个表
char sql[128] = "create table if not exists history (name char,word char,mean char,time char);";
char *errmsg = NULL;
char *name = save_buf;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
//插入记录
sprintf(sql,"insert into history values (\"%s\",\"%s\", \"%s\",\"%s\");",name,words, mean,mytime);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec failed:%s __%d__\n", errmsg, __LINE__);
return -1;
}
printf("Insert success...\n");
}
//查询单词
int Search(sqlite3 *db,char *buf,char *save_buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
char sql[128] = "select * from dict;";
char **pres = NULL;
int row,column;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_get_table: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char *words = buf+2;
for(int i=0;i<(row+1)*column;i++)
{
if(strcmp(pres[i],words) == 0)
{
//若查询成功,则将该单词插入记录
Insert(db,words,pres[i+1],save_buf);
bzero(buf, sizeof(buf));
sprintf(buf,"\t%s\t\t%s\t",pres[i],pres[i+1]);
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 4;
}
}
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 5;
}
4.1.5 查找历史记录
主要流程:
- 创建并打开数据库
- 创建数据表
- 匹配当前登录的用户名,若存在记录,则返回记录信息,若不存在,则查找失败
- 关闭数据库
//查询记录
int Search_res(sqlite3 *db,char *buf,char *save_buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
char sql[128] = "create table if not exists history (name char,word char,mean char,time char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char msg[128] = "";
strcpy(sql,"select * from history;");
char **pres = NULL;
int row,column;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_get_table: %s __%d__\n",errmsg,__LINE__);
return -1;
}
bzero(buf,sizeof(buf));
for(int i=4;i<(row+1)*column;i++)
{
if(i%4==0 && strcmp(save_buf,pres[i]) == 0)
{
sprintf(msg,"%s\t%s\t%s\t%s\n",pres[i],pres[i+1],pres[i+2],pres[i+3]);
strcat(buf,msg);
}
}
if(strlen(buf)!=0)
*(buf+strlen(buf)-1) = 0;
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
if(strlen(buf) == 0)
return 7;
return 6;
}
4.2 客户端实现功能代码
#include "head.h"
int main(int argc, const char *argv[])
{
sqlite3 *db = NULL;
//创建流式套接字
int cfd = socket(AF_INET,SOCK_STREAM,0);
if(cfd < 0)
{
perror("socket");
fprintf(stderr,"socket failed __%d__\n",__LINE__);
return -1;
}
printf("socket success...\n");
//设置允许端口号复用
int reuse = 1;
if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt");
return -1;
}
//填充地址信息结构体,真是的地址信息结构体根据地址族制定
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//连接服务器
if(connect(cfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("connetc");
return -1;
}
printf("connect success...\n");
ssize_t res = 0;
char buf[128] = "";
char save_buf[128] = "";
while(1)
{
system("clear");
printf("--------------------------\n");
printf("--------1.REGISTER--------\n");
printf("--------2.LOGIN-----------\n");
printf("--------3.EXIE------------\n");
printf("--------------------------\n");
bzero(buf,sizeof(buf));
printf("please enter>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
char name[20] = "";
char passwd[20] = "";
if(strcmp(buf,"1") == 0)
{
printf("please enter name>>>");
scanf("%s",name);
getchar();
printf("please enter passwd>>>");
scanf("%s",passwd);
getchar();
sprintf(buf,"%s%c%s%c%s","1",0,name,0,passwd);
}
else if(strcmp(buf,"2") == 0)
{
printf("please enter name>>>");
scanf("%s",name);
getchar();
printf("please enter passwd>>>");
scanf("%s",passwd);
getchar();
sprintf(buf,"%s%c%s%c%s","2",0,name,0,passwd);
}
else if(strcmp(buf,"3") == 0)
break;
//发送数据
if(send(cfd,buf,sizeof(buf),0) < 0)
{
perror("send");
return -1;
}
//接受数据
bzero(buf,sizeof(buf));
res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
perror("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] server offline\n",IP,PORT);
break;
}
printf("%s\n",buf);
//另存buf
strcpy(save_buf,buf);
while(strcmp(save_buf,"[login success!]") == 0)
{
system("clear");
printf("--------------------------\n");
printf("-------1.SEARCH WORDS-----\n");
printf("-------2.HISTORICAL ------\n");
printf("-------3.EXIE LOGIN-------\n");
printf("--------------------------\n");
bzero(buf,sizeof(buf));
printf("please enter>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
char words[20] = "";
if(strcmp(buf,"1") == 0)
{
while(1)
{
bzero(buf,sizeof(buf));
printf("please enter word(enter \"quit\" finished)>>>");
scanf("%s",words);
getchar();
if(strcmp(words,"quit") == 0)
break;
sprintf(buf,"%s%c%s%c","3",0,words,0);
//发送数据
if(send(cfd,buf,sizeof(buf),0) < 0)
{
perror("send");
return -1;
}
//接收查询单词结果
bzero(buf,sizeof(buf));
res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
perror("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] server offline\n",IP,PORT);
// break;
goto END;
}
printf("%s\n",buf);
}
}
else if(strcmp(buf,"2") == 0)
{
sprintf(buf,"%s%c","4",0);
//发送数据
if(send(cfd,buf,sizeof(buf),0) < 0)
{
perror("send");
return -1;
}
//接受查询单词结果
bzero(buf,sizeof(buf));
res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
perror("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] server offline\n",IP,PORT);
goto END;
// break;
}
printf("%s\n",buf);
}
else if(strcmp(buf,"3") == 0)
break;
printf("enter any character to clear>>>");
while(getchar()!=10);
}
printf("enter any character to clear>>>");
while(getchar()!=10);
}
END:
//关闭所有文件描述符
close(cfd);
return 0;
}
五、完整代码
5.1 头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>
#define PORT 8808
//#define IP "192.168.122.92"
#define IP "10.102.144.7"
#define ERR_MSG(msg) { fprintf(stderr,"__%d__",__LINE__); perror(msg); }
int import_dict(sqlite3 *db);
int Register(sqlite3 *db,char *buf);
int Login(sqlite3 *db,char *buf);
int Search(sqlite3 *db,char *buf,char *save_buf);
int Insert(sqlite3 *db,char *words,char *mean,char *save_buf);
int do_select_user(sqlite3 *db,char *name);
void handler(int sig);
int deal_cli_msg(int newfd,struct sockaddr_in cin,sqlite3 *db);
int Search_res(sqlite3 *db,char *buf,char *save_buf);
#endif
5.2 功能函数
#include "head.h"
//导入词典
int import_dict(sqlite3 *db)
{
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建一个表
char sql[128] = "create table if not exists dict (word char,mean char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
//打开文件
FILE* fp = fopen("./dict.txt", "r");
if(NULL == fp)
{
perror("fopen");
return -1;
}
//循环读取文件中的数据,一行一行的读取
char buf[256] = "";
char word[32] = "";
char mean[200] = "";
int count = 1;
int i = 0;
char* ptr = NULL;
printf("importing dictionary...\n");
while(1)
{
if(fgets(buf, sizeof(buf), fp) == NULL)
break;
buf[strlen(buf)-1] = 0;
//分离单词和意思
bzero(word, sizeof(word));
bzero(mean, sizeof(mean));
//获取" "子串在buf中的地址
ptr = strstr(buf, " ");
if(NULL == ptr)
{
printf("没有找到对应子串\n");
break;
}
strncpy(word, buf, ptr-buf); //" "子串前面是单词
strcpy(mean, ptr+3); //" "子串后面是意思
//插入到数据库中
sprintf(sql,"insert into dict values (\"%s\", \"%s\");", word, mean);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec failed:%s __%d__\n", errmsg, __LINE__);
return -1;
}
}
//关闭文件
fclose(fp);
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
printf("dictionary import completed...\n");
return 0;
}
//匹配用户名是否存在
int do_select_user(sqlite3 *db,char *name)
{
char sql[128] = "select name from user;";
char **pres = NULL;
int row,column;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
for(int i=1;i<(row+1)*column;i++)
{
if(strcmp(pres[i],name) == 0)
{
fprintf(stderr,"sqlite3_exec: name already existss\n");
return 1;
}
}
return 0;
}
//实现注册功能
int Register(sqlite3 *db,char *buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建一个表
char sql[128] = "create table if not exists user (name char,passwd char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char *name = buf+2;
char *passwd = buf+2+strlen(buf+2)+1;
if(do_select_user(db,name) == 1)
{
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 1;
}
sprintf(sql,"insert into user values ('%s','%s');",name,passwd);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
printf("register success...\n");
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 0;
}
//实现登录功能
int Login(sqlite3 *db,char *buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
char sql[128] = "create table if not exists user (name char,passwd char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
strcpy(sql,"select * from user;");
char **pres = NULL;
int row,column;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char *name = buf+2;
char *passwd = buf+2+strlen(buf+2)+1;
for(int i=2;i<(row+1)*column;i++)
{
if(strcmp(pres[i],name) == 0 && strcmp(pres[i+1],passwd) == 0)
{
printf("login success...\n");
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 2;
}
}
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 3;
}
//插入记录
int Insert(sqlite3 *db,char *words,char *mean,char *save_buf)
{
//获取当前时间
time_t t;
struct tm *info=NULL;
char mytime[128] = "";
t = time(NULL);
info = localtime(&t);
sprintf(mytime,"%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);
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
//创建一个表
char sql[128] = "create table if not exists history (name char,word char,mean char,time char);";
char *errmsg = NULL;
char *name = save_buf;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
//插入记录
sprintf(sql,"insert into history values (\"%s\",\"%s\", \"%s\",\"%s\");",name,words, mean,mytime);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec failed:%s __%d__\n", errmsg, __LINE__);
return -1;
}
printf("Insert success...\n");
}
//查询单词
int Search(sqlite3 *db,char *buf,char *save_buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
char sql[128] = "select * from dict;";
char **pres = NULL;
int row,column;
char *errmsg = NULL;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_get_table: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char *words = buf+2;
for(int i=0;i<(row+1)*column;i++)
{
if(strcmp(pres[i],words) == 0)
{
//若查询成功,则将该单词插入记录
Insert(db,words,pres[i+1],save_buf);
bzero(buf, sizeof(buf));
sprintf(buf,"\t%s\t\t%s\t",pres[i],pres[i+1]);
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 4;
}
}
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
return 5;
}
//查询记录
int Search_res(sqlite3 *db,char *buf,char *save_buf)
{
//打开数据库
if(sqlite3_open("./dict.db",&db) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);
return -1;
}
char sql[128] = "create table if not exists history (name char,word char,mean char,time char);";
char *errmsg = NULL;
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);
return -1;
}
char msg[128] = "";
strcpy(sql,"select * from history;");
char **pres = NULL;
int row,column;
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr,"sqlite3_get_table: %s __%d__\n",errmsg,__LINE__);
return -1;
}
bzero(buf,sizeof(buf));
for(int i=4;i<(row+1)*column;i++)
{
if(i%4==0 && strcmp(save_buf,pres[i]) == 0)
{
sprintf(msg,"%s\t%s\t%s\t%s\n",pres[i],pres[i+1],pres[i+2],pres[i+3]);
strcat(buf,msg);
}
}
if(strlen(buf)!=0)
*(buf+strlen(buf)-1) = 0;
//关闭数据库,释放对应的内存空间
if(sqlite3_close(db) != SQLITE_OK)
{
printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);
return -1;
}
if(strlen(buf) == 0)
return 7;
return 6;
}
//服务器子进程处理客户端信息
int deal_cli_msg(int newfd,struct sockaddr_in cin,sqlite3 *db)
{
int flag = 0;
char buf[128] = "";
char save_buf[128] = "";
ssize_t res = 0;
int f_res = -1;
while(1)
{
bzero(buf, sizeof(buf));
//接收数据
res = recv(newfd, buf, sizeof(buf), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] client offline\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
break;
}
//调用功能函数
if(strcmp(buf,"1") == 0)
f_res = Register(db,buf); //注册
else if(strcmp(buf,"2") == 0)
{
f_res = Login(db,buf); //登录
strcpy(save_buf,buf+2); //将用户名另存
}
else if(strcmp(buf,"3") == 0)
{
f_res = Search(db,buf,save_buf); //查询单词
}
else if(strcmp(buf,"4") == 0)
f_res = Search_res(db,buf,save_buf); //查询记录
//发送数据
if(0 == f_res)
{
bzero(buf, sizeof(buf));
strcpy(buf,"[register success!]");
}
else if(1 == f_res)
{
bzero(buf, sizeof(buf));
strcpy(buf,"[register failed,name already exists!]");
}
else if(2 == f_res)
{
bzero(buf, sizeof(buf));
strcpy(buf,"[login success!]");
}
else if(3 == f_res)
{
bzero(buf, sizeof(buf));
strcpy(buf,"[login failed,name/passwd does not exists!]");
}
else if(4 == f_res)
{
}
else if(5 == f_res)
{
bzero(buf, sizeof(buf));
strcpy(buf,"[words not find!]");
}
else if(6 == f_res)
{
}
else if(7 == f_res)
{
bzero(buf, sizeof(buf));
strcpy(buf,"[not find history!]");
}
if(send(newfd, buf, sizeof(buf), 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
close(newfd);
return 0;
}
//捕获信号
void handler(int sig)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
5.3 服务器
#include "head.h"
int main(int argc, const char *argv[])
{
sqlite3 *db = NULL;
if(signal(17, handler) == SIG_ERR)
{
ERR_MSG("signal");
return -1;
}
//导入词典
import_dict(db);
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//设置允许端口号复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt");
return -1;
}
//绑定服务器IP和端口号
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
//将套接字设置为被动监听状态
if(listen(sfd,10) < 0)
{
ERR_MSG("listen");
return -1;
}
int newfd = -1;
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
//从已完成连接的队列中获取一个客户端信息,生成一个新的文件描述符
while(1)
{
newfd = accept(sfd,(struct sockaddr *)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s : %d] connect success...\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
if(0 == fork())
{
close(sfd);
deal_cli_msg(newfd,cin,db);
exit(0);
}
close(newfd);
}
close(sfd);
return 0;
}
5.4 客户端
#include "head.h"
int main(int argc, const char *argv[])
{
sqlite3 *db = NULL;
//创建流式套接字
int cfd = socket(AF_INET,SOCK_STREAM,0);
if(cfd < 0)
{
perror("socket");
fprintf(stderr,"socket failed __%d__\n",__LINE__);
return -1;
}
printf("socket success...\n");
//设置允许端口号复用
int reuse = 1;
if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt");
return -1;
}
//填充地址信息结构体,真是的地址信息结构体根据地址族制定
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//连接服务器
if(connect(cfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("connetc");
return -1;
}
printf("connect success...\n");
ssize_t res = 0;
char buf[128] = "";
char save_buf[128] = "";
while(1)
{
system("clear");
printf("--------------------------\n");
printf("--------1.REGISTER--------\n");
printf("--------2.LOGIN-----------\n");
printf("--------3.EXIE------------\n");
printf("--------------------------\n");
bzero(buf,sizeof(buf));
printf("please enter>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
char name[20] = "";
char passwd[20] = "";
if(strcmp(buf,"1") == 0)
{
printf("please enter name>>>");
scanf("%s",name);
getchar();
printf("please enter passwd>>>");
scanf("%s",passwd);
getchar();
sprintf(buf,"%s%c%s%c%s","1",0,name,0,passwd);
}
else if(strcmp(buf,"2") == 0)
{
printf("please enter name>>>");
scanf("%s",name);
getchar();
printf("please enter passwd>>>");
scanf("%s",passwd);
getchar();
sprintf(buf,"%s%c%s%c%s","2",0,name,0,passwd);
}
else if(strcmp(buf,"3") == 0)
break;
//发送数据
if(send(cfd,buf,sizeof(buf),0) < 0)
{
perror("send");
return -1;
}
//接受数据
bzero(buf,sizeof(buf));
res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
perror("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] server offline\n",IP,PORT);
break;
}
printf("%s\n",buf);
//另存buf
strcpy(save_buf,buf);
while(strcmp(save_buf,"[login success!]") == 0)
{
system("clear");
printf("--------------------------\n");
printf("-------1.SEARCH WORDS-----\n");
printf("-------2.HISTORICAL ------\n");
printf("-------3.EXIE LOGIN-------\n");
printf("--------------------------\n");
bzero(buf,sizeof(buf));
printf("please enter>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
char words[20] = "";
if(strcmp(buf,"1") == 0)
{
while(1)
{
bzero(buf,sizeof(buf));
printf("please enter word(enter \"quit\" finished)>>>");
scanf("%s",words);
getchar();
if(strcmp(words,"quit") == 0)
break;
sprintf(buf,"%s%c%s%c","3",0,words,0);
//发送数据
if(send(cfd,buf,sizeof(buf),0) < 0)
{
perror("send");
return -1;
}
//接收查询单词结果
bzero(buf,sizeof(buf));
res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
perror("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] server offline\n",IP,PORT);
// break;
goto END;
}
printf("%s\n",buf);
}
}
else if(strcmp(buf,"2") == 0)
{
sprintf(buf,"%s%c","4",0);
//发送数据
if(send(cfd,buf,sizeof(buf),0) < 0)
{
perror("send");
return -1;
}
//接受查询单词结果
bzero(buf,sizeof(buf));
res = recv(cfd,buf,sizeof(buf),0);
if(res < 0)
{
perror("recv");
return -1;
}
else if(0 == res)
{
printf("[%s : %d] server offline\n",IP,PORT);
goto END;
// break;
}
printf("%s\n",buf);
}
else if(strcmp(buf,"3") == 0)
break;
printf("enter any character to clear>>>");
while(getchar()!=10);
}
printf("enter any character to clear>>>");
while(getchar()!=10);
}
END:
//关闭所有文件描述符
close(cfd);
return 0;
}