终端:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define DATABASE "my.db"
#define N 16
enum CMD
{
R = 1,
L,
Q,
H
};
typedef struct sockaddr SA;
typedef struct
{
int type;
char name[N];
char data[256]; // password or word
} MSG;
static sqlite3 *db;
/**
* @brief 服务器处理注册
* 得到用户输入用户名和密码并拼接sql语句
* 执行sql语句
* 封装执行结果并回发客户端
*/
void do_register(int connfd, MSG *pbuf)
{
char *errmsg = NULL;
char sql[300] = "";
int row = 0;
int column = 0;
char **result = NULL;
//用户名是否存在
sprintf(sql, "select * from usr where name =\"%s\";", pbuf->name);
int sr;
sr = sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);
printf("%s\n", sql);
//判断用户信息已经存在
if (row > 0)
{
char ra[300] = {0};
sprintf(ra, "user\"%s\"already exist!!!", pbuf->name);
printf("%s\n", ra);
send(connfd, ra, 300, 0);
}
//用户信息不存在,插入用户信息
else
{
//插入数据
char sqll[300] = "";
sprintf(sqll, "insert into usr values(\"%s\",\"%s\");", pbuf->name, pbuf->data);
if (sqlite3_exec(db, sqll, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "insert err:%s\n", errmsg);
return;
}
else
{
printf("insert ok\n");
char i[300] = "register :ok";
send(connfd, i, 300, 0);
}
}
}
/**
* @brief 服务器处理登录
* 得到用户输入用户名和密码并拼接sql语句
* 执行sql语句
* 封装执行结果并回发客户端
*/
void do_login(int connfd, MSG *pbuf)
{
int sr;
char **result = NULL;
int row = 0; //行
int column = 0; //列
int k = 0; //result下标
char *errmsg = NULL;
char sql[300] = "";
//用户名
sprintf(sql, "select * from usr where name=\"%s\";", pbuf->name);
sr = sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);
//用户信息存在
if (row > 0)
{
row = 0;
char s[300] = "";
//用户名加密码
sprintf(s, "select * from usr where name=\"%s\" and pass= \"%s\";", pbuf->name, pbuf->data);
int srr;
srr = sqlite3_get_table(db, s, &result, &row, &column, &errmsg);
if (row > 0)
//密码正确
{
char c[300] = "login success";
send(connfd, c, 300, 0);
}
else
//密码错误
{
printf("%s\n", s);
char b[300] = "name err";
send(connfd, b, 300, 0);
}
}
else
{
//不存在,先注册
char a[300] = "please register";
send(connfd, a, 300, 0);
}
}
/*
* @brief 查询单词释义
* @return 查询成功返回1 失败返回0
*/
int do_searchword(int connfd, MSG *pbuf)
{
char **result = NULL;
int row = 0; //行
int column = 0; //列
char *errmsg = NULL;
char sql[300] = "";
//打开表dic
// if (sqlite3_exec(db, "create table dic(word char,parse char);", NULL, NULL, &errmsg) != SQLITE_OK)
// {
// fprintf(stderr, "create err:%s\n", errmsg);
// }
// else
// printf("dic open ok\n");
// //设置键值
if (sqlite3_exec(db, "create table dic( word char primary key,parse char);", NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "create key err:%s\n", errmsg);
}
sprintf(sql, "select * from dic where word = \"%s\";", pbuf->data);
if (sqlite3_get_table(db, sql, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "select err:%s\n", errmsg);
}
if (row == 0)
{ //没找到
strcpy(pbuf->data,"该单词不存在");
printf("%s\n", pbuf->data);
send(connfd, pbuf,sizeof(MSG), 0);
memset(pbuf->data,0,sizeof(pbuf->data));
return 0;
}
else if (row > 0)
{
printf("row:%d cou:%d\n", row, column); //查询的单词信息
int k = 3; //下表
for (int i = 0; i < row; i++)
{
for (int j = 1; j < column; j++)//每行就打印一个字符串
{
//k,只能查三个单词
sprintf(pbuf->data,"%s " ,result[k]); //j=0,result[k]最后越界
send(connfd, pbuf, sizeof(MSG), 0);
k=k+2;
memset(pbuf->data,0,sizeof(pbuf->data));
}
strcpy(pbuf->data, "\n");
send(connfd, pbuf, sizeof(MSG), 0);
}
strcpy(pbuf->data, "over");
send(connfd, pbuf, sizeof(MSG), 0);
return 1;
}
}
/**
* @brief 返回当前的时间,存到date中
* @return
*/
void get_date(char *date)
{
time_t t;
struct tm *tp;
time(&t);
tp = localtime(&t);
sprintf(date, "%d-%02d-%02d %02d:%02d:%02d", tp->tm_year + 1900,
tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
strftime(date, 64, "%Y-%m-%d %H:%M:%S", tp);
return;
}
/**
* @brief 服务器处理查询
* 查询单词释义
* 把本次查询添加到查询历史中
*/
void do_query(int connfd, MSG *pbuf)
{
char *errmsg = NULL;
int ret;
char buf[300] = "";
strcpy(buf, pbuf->data);
ret = do_searchword(connfd, pbuf);
if (ret == 1)
{
//打开表
// if (sqlite3_exec(db, "create table record(name char,data char,word char);", NULL, NULL, &errmsg) != SQLITE_OK)
// {
// fprintf(stderr, "create err:%s\n", errmsg);
// }
// else
// printf("dic open ok\n");
// // //设置键值
// if (sqlite3_exec(db, "create table record(name char primary key,data char,word char);", NULL, NULL, &errmsg) != SQLITE_OK)
// {
// fprintf(stderr, "create key err:%s\n", errmsg);
// }
char sqll[300] = "";
char date[128] = "";
get_date(date);
sprintf(sqll, "insert into record values(\"%s\",\"%s\",\"%s\");", pbuf->name, date, buf);
if (sqlite3_exec(db, sqll, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "insert err:%s\n", errmsg);
return;
}
else
{
printf("insert ok\n");
}
}
}
/**
* @brief 查询历史处理
* 根据用户名来查找查询历史,并将结果返回给客户端
* 执行sql语句
* 封装执行结果并回发客户端
*/
void do_history(int connfd, MSG *pbuf)
{
char **result = NULL;
int row = 0; //行
int column = 0; //列
char *errmsg = NULL;
char sql[300] = "";
// sprintf(sql, "select *from record where name= \"%s\";", pbuf->name);
sprintf(sql, "select date,word from record where name= \"%s\";", pbuf->name);//**注意**
if (sqlite3_get_table(db, sql, &result, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "select err:%s\n", errmsg);
}
printf("row:%d cou:%d\n", row, column); //查询的单词信息
if (row > 0)
{ //查询的信息
int k = 0; //下表
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
sprintf(pbuf->data, "%s ", result[k++]);
printf("%s\n", pbuf->data);
send(connfd, pbuf, sizeof(MSG), 0);
}
strcpy(pbuf->data, "\n");
send(connfd, pbuf, sizeof(MSG), 0);
}
strcpy(pbuf->data, "over");
send(connfd, pbuf, sizeof(MSG), 0);
}
return;
}
/**
* @brief do_client 处理客户端请求
* @param connfd 客户端fd
* @param db 数据库句柄
*/
void do_client(int connfd)
{
MSG buf;
while (recv(connfd, &buf, sizeof(buf), 0) > 0)
{
switch (buf.type)
{
case R:
printf("will reg\n");
do_register(connfd, &buf);
break;
case L:
printf("will login\n");
do_login(connfd, &buf);
break;
case Q:
printf("will query\n");
do_query(connfd, &buf);
break;
case H:
printf("will history\n");
do_history(connfd, &buf);
break;
default:
break;
}
}
exit(0);
}
int main(int argc, char *argv[])
{
int listenfd, connfd;
struct sockaddr_in myaddr;
pid_t pid;
MSG buf;
if (argc < 3)
{
printf("Usage : %s <ip> <port>\n", argv[0]);
exit(-1);
}
//打开数据库
// if (sqlite3_open(DATABASE, &db) < 0)
// {
// printf("fail to sqlite3_open : %s\n", sqlite3_errmsg(db));
// return -1;
// }
char *errmsg = NULL;
if (sqlite3_open("./my.db", &db) != SQLITE_OK)
{
fprintf(stderr, "open err:%s\n", sqlite3_errmsg(db));
return -1;
}
printf("open ok\n");
// //打开表
// if (sqlite3_exec(db, "create table usr( name char, pass char);", NULL, NULL, &errmsg) != SQLITE_OK)
// {
// fprintf(stderr, "create err:%s\n", errmsg);
// }
// else
// printf("create ok\n");
//设置键值,键值唯一,不会重复
if (sqlite3_exec(db, "create table usr(name char primary key,pass char);", NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "create key err:%s\n", errmsg);
}
//创建服务器socket
listenfd = socket(PF_INET, SOCK_STREAM, 0);
if (listenfd < 0)
{
perror("fail to socket");
exit(-1);
} //
bzero(&myaddr, sizeof(myaddr));
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(atoi(argv[2]));
myaddr.sin_addr.s_addr = inet_addr(argv[1]);
if (bind(listenfd, (SA *)&myaddr, sizeof(myaddr)) < 0)
{
perror("fail to bind");
exit(-1);
}
// XXX int listen(int sockfd, int backlog);
if (listen(listenfd, 5) < 0)
{
perror("fail to listen");
exit(-1);
}
//并发服务器模型
while (1)
{
if ((connfd = accept(listenfd, NULL, NULL)) < 0)
{
perror("fail to accept");
exit(-1);
}
pid = fork();
if (pid == -1)
{
perror("fail to fork\n");
exit(-1);
}
else if (pid == 0)
{ //子进程
printf("a user comming\n");
do_client(connfd);
}
else
{ //父进程
close(connfd);
}
}
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 16
typedef struct sockaddr SA;
enum CMD
{
R = 1, //注册
L, //登录
Q, //查询
H //历史
};
typedef struct
{
int type;
char name[N];
char data[256]; // password or word
} MSG;
static sqlite3 *db;
/**
* @brief 客户端注册
* 用户输入用户名和密码
* 封装消息
* 发送
* 接收并输出结果
*/
void do_register(int sockfd, MSG *pbuf)
{
pbuf->type = R;
//接收数据
char r[300] = "";
//插入数据
printf("input name : ");
fgets(pbuf->name, sizeof(pbuf->name), stdin);
if (pbuf->name[strlen(pbuf->name) - 1] == '\n')
pbuf->name[strlen(pbuf->name) - 1] = '\0';
printf("input password : ");
fgets(pbuf->data, sizeof(pbuf->data), stdin);
if (pbuf->data[strlen(pbuf->data) - 1] == '\n')
pbuf->data[strlen(pbuf->data) - 1] = '\0';
send(sockfd, pbuf, sizeof(MSG), 0);
//用户名已存在或注册成功
recv(sockfd, r, 300, 0);
printf("%s\n", r);
}
/**
* @brief 客户端登录
* 用户输入用户名和密码
* 封装消息
* 发送
* 接收并输出结果
* @return 成功返回1 失败返回0
*/
int do_login(int sockfd, MSG *pbuf)
{
char r[300] = "";
pbuf->type = L;
printf("input name: ");
fgets(pbuf->name, sizeof(pbuf->name), stdin);
if (pbuf->name[strlen(pbuf->name) - 1] == '\n')
pbuf->name[strlen(pbuf->name) - 1] = '\0';
printf("input password: ");
fgets(pbuf->data, sizeof(pbuf->data), stdin);
if (pbuf->data[strlen(pbuf->data) - 1] == '\n')
pbuf->data[strlen(pbuf->data) - 1] = '\0';
send(sockfd, pbuf, sizeof(MSG), 0);
//接收执行结果
recv(sockfd, r, 300, 0);
printf("%s\n", r);
if (strcmp(r, "login success") == 0)
return 1;
else
return 0;
}
/**
* @brief 客户端查询
* 查询历史
*/
void do_history(int sockfd, MSG *pbuf)
{
pbuf->type = H;
send(sockfd, pbuf, sizeof(MSG), 0);
while (1)
{
recv(sockfd, pbuf, sizeof(MSG), 0);
if (!strcmp(pbuf->data, "over"))
break;
printf("%s", pbuf->data);
memset(pbuf->data, 0, sizeof(pbuf->data));
}
}
/**
* @brief 客户端查询
* 输入单词或“#”
* 封装消息
* 发送
* 接收并输出结果
*/
void do_query(int sockfd, MSG *pbuf)
{
pbuf->type = Q;
while (1)
{
printf("input word(# to quit): ");
fgets(pbuf->data, sizeof(pbuf->data), stdin);
if (pbuf->data[strlen(pbuf->data) - 1] == '\n')
pbuf->data[strlen(pbuf->data) - 1] = '\0';
if (strcmp(pbuf->data, "#") == 0)
return;
send(sockfd, pbuf, sizeof(MSG), 0);
//接收查询信息
while (1)
{
recv(sockfd, pbuf, sizeof(MSG), 0);
if (!strcmp(pbuf->data, "over"))
break;
if (!strcmp(pbuf->data, "该单词不存在"))
{
printf("%s \n", pbuf->data);
break;
}
printf("%s \n", pbuf->data);
}
}
}
void enter_query(int sockfd, MSG *buf)
{
int input;
char cleanbuf[64];
while (1)
{
printf("***********************************************\n");
printf("* 1: query_word 2: history_record 3: quit *\n");
printf("***********************************************\n");
printf("please choose : ");
//获取用户输入
if (scanf("%d", &input) == 0)
{
fgets(cleanbuf, 64, stdin); //类型错误需要重新清除输入缓冲区
continue;
}
getchar();
switch (input)
{
case 1:
printf("\n");
do_query(sockfd, buf);
printf("\n");
break;
case 2:
printf("\n");
do_history(sockfd, buf);
printf("\n");
break;
case 3:
return;
default:
break;
}
}
}
int main(int argc, char *argv[])
{
int sockfd, login = 0;
struct sockaddr_in servaddr;
MSG buf;
char clean[64];
if (argc < 3)
{
printf("Usage : %s <serv_ip> <serv_port>\n", argv[0]);
exit(-1);
}
//创建客户端socket
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("fail to socket");
exit(-1);
}
int optval = 1;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = PF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
//连接服务器
if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0)
{
perror("fail to connect");
exit(-1);
}
int input;
char cleanbuf[64];
while (1)
{
printf("************************************\n");
printf("* 1: register 2: login 3: quit *\n");
printf("************************************\n");
printf("please choose : ");
//获取用户输入
if (scanf("%d", &input) == 0)
{
fgets(cleanbuf, 64, stdin); //类型错误需要重新清除输入缓冲区
continue;
}
getchar(); //回收回车
switch (input)
{
case 1:
do_register(sockfd, &buf);
break;
case 2:
if (do_login(sockfd, &buf) == 1)
{
enter_query(sockfd, &buf);
}
break;
case 3:
close(sockfd);
exit(0);
break;
default:
break;
}
}
}