头文件:
- #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;
-
- }