头文件:
#ifndef __HEAD_H__
#define __HEAD_H__
#include
#define N 32
typedef struct {
int type;
char name[N];
char data[256];
int option;
int flag;
}MSG;
#define R 1 // 用户注册
#define L 2 // 用户登录
#define Q 3 // 查询单词
#define H 4 // 历史记录
#define DATABASE "my.db" //创建的数据库
#define SERADDR "192.168.114.156"
#define SERPORT 8888
#endif
服务器:
#include "head.h"
void init_sql(sqlite3 *db);
int do_client(int acceptfd, sqlite3 *db); //客户端请求入口
void do_register(int acceptfd, MSG *msg, sqlite3 *db);//注册用户实现
int do_login(int acceptfd, MSG *msg, sqlite3 *db);//用户登录实现
int do_query(int acceptfd, MSG *msg, sqlite3 *db);//用户查询单词实现
int do_history(int acceptfd, MSG *msg, sqlite3 *db);//查询历史记录
int get_data(char *date);//获取时间
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in serveraddr;
int acceptfd;
sqlite3 *db;
pid_t pid;
//打开数据库
if(sqlite3_open(DATABASE, &db) != SQLITE_OK)
{
printf("%s\n", sqlite3_errmsg(db));
return -1;
}
else
{
printf("open DATABASE success.\n");
}
//套接字
if((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0)
{
perror("fail to socket.\n");
return -1;
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(SERADDR);
serveraddr.sin_port = htons(SERPORT);
int reuse = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt");
return -1;
}
//绑定
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("fail to bind.\n");
return -1;
}
//监听
if(listen(sockfd, 5) < 0)
{
printf("fail to listen.\n");
return -1;
}
signal(SIGCHLD, SIG_IGN); //处理僵尸进程
if (sqlite3_open("./my.db", &db) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite_open:%s\n", __LINE__, sqlite3_errmsg(db));
return -1;
}
init_sql(db);
struct sockaddr_in cin;
socklen_t cin_len = sizeof(cin);
while(1)
{
//接收
if((acceptfd = accept(sockfd, NULL, NULL)) < 0)
{
perror("fail to accept");
return -1;
}
//创建子进程
if((pid = fork()) < 0)
{
perror("fail to fork");
return -1;
}
//子进程
else if(pid == 0)
{
close(sockfd);
do_client(acceptfd, db);
}
//父进程
else
{
close(acceptfd);
}
}
return 0;
}
//客户端请求入口
int do_client(int acceptfd, sqlite3 *db)
{
MSG msg;
while(recv(acceptfd, &msg, sizeof(msg), 0) > 0)
{
switch(msg.option)
{
case R:
do_register(acceptfd, &msg, db);
break;
case L:
do_login(acceptfd, &msg, db);
break;
case Q:
do_query(acceptfd, &msg, db);
break;
case H:
do_history(acceptfd, &msg, db);
break;
default:
printf("Invalid data msg.\n");
}
}
printf("用户已退出\n");
close(acceptfd);
exit(0);
return 0;
}
//数据库操作
void init_sql(sqlite3 *db)
{
printf("正在初始化...\n");
//创建表
char sql[256] = "";
char *errmsg = NULL;
strcpy(sql, "create table if not exists usr (name char PRIMARY KEY,passwd char,status char);");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error:%s\n", errmsg);
return;
}
strcpy(sql, "create table if not exists log (name char,word char,explain char,time char);");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error:%s\n", errmsg);
return;
}
strcpy(sql, "create table if not exists dict (Word char,Explain char);");
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error:%s\n", errmsg);
return;
}
//判断词库存不存在
char **result = NULL;
int rows = 1;
int columns = 0;
// char sql[128] = "select * from stu";
strcpy(sql, "select * from dict");
if (sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg) != SQLITE_OK)
{
printf("sqlite3_get_table error:%s line=%d\n", errmsg, __LINE__);
return;
}
sqlite3_free_table(result);
if (rows < 7987)
{
printf("正在导入词库...\n");
FILE *fp = fopen("./dict.txt", "r");
if (NULL == fp)
{
perror("fopen");
return;
}
char buff[300];
char Word[64];
char Explain[256];
char *p = NULL;
while (NULL != fgets(buff, sizeof(buff), fp))
{
p = buff;
while (1)
{
if (*p != ' ' || (*p == ' ' && *(p + 1) != ' '))
p++;
else
break;
}
*p = '\0';
p++;
//获取单词
strcpy(Word, buff);
//跳过空格
while (*p == ' ')
{
p++;
}
//截取解释
strcpy(Explain, p);
sprintf(sql, "insert into dict values(\"%s\",\"%s\")", Word, Explain);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error:%s line=%d\n", errmsg, __LINE__);
return;
}
}
}
printf("单词库导入成功\n");
}
void do_register(int acceptfd, MSG *msg, sqlite3 *db)//注册用户实现
{
char sql[512] = {0};
char *errmsg;
sprintf(sql, "insert into usr values(\"%s\",\"%s\",'no');", msg->name, msg->data);
// name为主键,插入失败则用户名已经存在
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
// printf("sqlite3_exec error:%s line=%d\n", errmsg, __LINE__);
sprintf(msg->data, "用户名 %s 已存在!!", msg->name);
}
else
{ printf("新用户:%s 已注册\n",msg->name);
strcpy(msg->data, "注册成功!!");
}
send(acceptfd, msg, sizeof(MSG), 0);
return;
}
int do_login(int acceptfd, MSG *msg, sqlite3 *db)//用户登录实现
{
char sql[512] = {0};
char *errmsg, **result;
int rows, columns;
//通过sqlite3_get_table函数查询记录是否存在
sprintf(sql, "select * from usr where name = '%s' and passwd = '%s'", msg->name, msg->data);
if (sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg) != SQLITE_OK)
{
printf("sqlite3_get_table error:%s line=%d\n", errmsg, __LINE__);
}
//通过row参数判断是否能够查询到疾记录,如果值为0,则查询不到,如果值为非0,则查询到
if (rows == 0)
{
strcpy(msg->data, "登录失败,用户名或密码错误");
msg->flag = 0; //失败
}
else
{
strcpy(msg->data, "登录成功");
sprintf(sql, "update usr set status = 'yes' where name = '%s'", msg->name); //登录之后状态设置为yes;
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error:%s line=%d\n", errmsg, __LINE__);
}
msg->flag = 1; //成功
printf("用户%s已登录\n", msg->name);
}
send(acceptfd, msg, sizeof(MSG), 0);
return 0;
}
int do_query(int acceptfd, MSG *msg, sqlite3 *db)//用户查询单词实现
{
char sql[512] = "", *errmsg = NULL;
int found = 0;
char date[128];
char **result = NULL;
int rows = 0;
int columns = 0;
sprintf(sql, "select * from dict where Word='%s'", msg->data);
if (sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg) != SQLITE_OK)
{
printf("sqlite3_get_table error:%s line=%d\n", errmsg, __LINE__);
return -1;
}
if (0 == rows)//没有查到
{
strcpy(msg->data, "Not Found!!!");
send(acceptfd, msg, sizeof(MSG), 0);
}
else
{
printf("%s\t\t%s\n", result[2], result[3]);
strcpy(msg->data, result[3]);
//如果执行成功,还需要保存历史记录
//获取时间
get_data(date);
//通过sqlite3_exec函数插入数据
bzero(sql, sizeof(sql));
sprintf(sql, "insert into log values('%s', '%s', '%s', '%s')", msg->name, result[2], result[3], date);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("sqlite3_exec error:%s line=%d\n", errmsg, __LINE__);
}
printf("%s 查询成功\n",msg->name);
send(acceptfd, msg, sizeof(MSG), 0);
}
return 0;
}
int do_history(int acceptfd, MSG *msg, sqlite3 *db)//查询历史记录
{
char sql[512] = "", *errmsg = NULL;
int found = 0;
char info[512];
char **result = NULL;
int rows = 0;
int columns = 0;
printf("%s 正在查询记录...\n", msg->name);
sprintf(sql, "select * from log where name='%s'", msg->name);
if (sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg) != SQLITE_OK)
{
printf("sqlite3_get_table error:%s line=%d\n", errmsg, __LINE__);
return -1;
}
//将记录逐条发送给客户端
for (int i = 1; i <= rows; i++)
{
sprintf(info, "%s:\t%s\t%s\t%s\n", result[i * columns], result[i * columns + 1], result[i * columns + 2], result[i * columns + 3]);
send(acceptfd, info, sizeof(info), 0);
}
strcpy(info, "已到末尾");
send(acceptfd, info, sizeof(info), 0);
return 1;
}
int get_data(char *date)//获取时间
{
time_t t;
struct tm *tp;
time(&t);
tp = localtime(&t);
sprintf(date, "历史时间:%d-%02d-%02d %02d:%02d:%02d",
1900 + tp->tm_year, 1 + tp->tm_mon, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec);
}
客户端:
#include "head.h"
int do_register(int sockfd, MSG *msg); //注册用户
int do_login(int sockfd, MSG *msg); //用户登录
int do_query(int sockfd, MSG *msg); //查询单词
int do_history(int sockfd, MSG *msg); //查询历史
int SubMenu(int sockfd); //查询界面
char name[20];
int flag=0;
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in serveraddr;
int n;
MSG msg;
if((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0)
{
perror("fail to socket.\n");
return -1;
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(SERADDR);
serveraddr.sin_port = htons(SERPORT);
if(connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("fail to connect");
return -1;
}
while(1)
{
printf("*****************************登录界面****************************\n");
printf("**********************请输入序号进行对应操作*********************\n");
printf("****************************1.注册*******************************\n");
printf("****************************2.登录*******************************\n");
printf("****************************3.退出*******************************\n");
printf("请输入>>>");
scanf("%d", &n);
getchar();
switch(n)
{
case 1:
do_register(sockfd, &msg);
break;
case 2:
if(do_login(sockfd, &msg) == 1)
{
SubMenu(sockfd);
}
break;
case 3:
close(sockfd);
exit(0);
break;
default:
printf("输入不合法,请重新输入\n");
}
}
return 0;
}
int SubMenu(int sockfd)
{
int n;
MSG msg;
while(1)
{
printf("*****************************查询界面****************************\n");
printf("**********************请输入序号进行对应操作*********************\n");
printf("**************************1.查询单词*****************************\n");
printf("**************************2.查询历史记录*************************\n");
printf("**************************3.退出*****************************\n");
printf("请输入>>>");
scanf("%d", &n);
getchar();
switch(n)
{
case 1:
do_query(sockfd, &msg);
break;
case 2:
do_history(sockfd, &msg);
break;
case 3:
close(sockfd);
exit(0);
break;
default :
printf("Invalid data cmd.\n");
}
}
return 0;
}
int do_register(int sockfd, MSG *msg) //注册用户
{
msg->option = R;
printf("请输入要注册的用户名>>>");
scanf("%s", msg->name);
while (getchar() != 10)
;
printf("请输入密码>>>");
scanf("%s", msg->data);
while (getchar() != 10)
;
//将用户名及密码发送给服务器,判断是否存在
send(sockfd, msg, sizeof(MSG), 0);
recv(sockfd, msg, sizeof(MSG), 0);
//接收服务器发回来的消息来判断是否成功
printf("Register: %s\n", msg->data);
return 0;
}
int do_login(int sockfd, MSG *msg) //用户登录
{
//设置操作码
msg->option = L;
//输入用户名
printf("请输入用户名>>>");
scanf("%s", msg->name);
while (getchar() != 10)
;
//输入密码
printf("请输入密码>>>");
scanf("%s", msg->data);
while (getchar() != 10)
;
//发送数据给服务器
send(sockfd, msg, sizeof(MSG), 0);
//接收服务器发送的数据
recv(sockfd, msg, sizeof(MSG), 0);
//判断是否登录成功
printf("%s\n", msg->data);
if (msg->flag == 0)
{
return 0;
}
else
{
strcpy(name, msg->name);
return 1;
}
}
int do_query(int sockfd, MSG *msg) //查询单词
{
msg->option = Q;
strcpy(msg->name, name);
printf("-----------------------------单词查询中-----------------------------\n");
while (1)
{
printf("请输入单词 (输入88退出): ");
scanf("%s", msg->data);
while (getchar() != 10)
;
//如果输入的是#,返回
if (strcmp(msg->data, "88") == 0)
{
break;
}
send(sockfd, msg, sizeof(MSG), 0);
recv(sockfd, msg, sizeof(MSG), 0);
printf("EXPLANTION %s\n", msg->data);
}
return 0;
}
int do_history(int sockfd, MSG *msg) //查询历史
{
char info[512];
msg->option = H;
strcpy(msg->name, name);
send(sockfd, msg, sizeof(MSG), 0);
while (1)
{
recv(sockfd, info, sizeof(info), 0);
printf("%s\n", info);
if (0 == strcmp(info, "已到末尾"))
{
break;
}
}
return 0;
}