1.客户端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg) do{\
perror(msg);\
printf("line: __%d__\n", __LINE__);\
}while(0);
#define IP_SER "192.168.8.66"
#define POST_SER 8888
//协议信息结构体
struct message
{
char type; //L:登录 R:注册 S:查询 H:查询历史信息
char name[16]; //l:登录成功 r:注册成功标志 s:返回查询成功 h:查询结束标志
char passward[16];
char chinese[64]; //中文意思 登录信息(登录失败原因:账号不存在或者密码错误)
char english[64];
};
//存储客户端对应的cin和fd的结构体,是线程创建的参数
struct cin_info
{
int newfd;
struct sockaddr_in cin;
};
//线程回调处理客户端需求函数
void* cin_deal(void* arg);
//switch分支函数
int do_login(struct message cin_message, struct cin_info* user_cin);
int do_region(struct message cin_message, struct cin_info* user_cin);
int do_search(struct message cin_message, struct cin_info* user_cin);
int do_history(struct message cin_message, struct cin_info* user_cin);
int do_select();
//记录用户账号密码的数据库权柄
sqlite3* db_user = NULL;
//电子词典的数据库权柄
sqlite3* db = NULL;
//历史记录的数据库权柄
sqlite3* db_history = NULL;
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET, SOCK_STREAM, 0); //创建套接字
if (sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket success sfd = %d\n", sfd);
int reuse = 1;
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口重用\n");
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(POST_SER);
sin.sin_addr.s_addr = inet_addr(IP_SER);
if (bind(sfd, (struct sockaddr*)&sin, (socklen_t)sizeof(sin)) < 0)//连接套接字
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
if(listen(sfd, 128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
//创建用户数据库
if (sqlite3_open("./user.db", &db_user) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open : %s errcode : %d\n", sqlite3_errmsg(db_user), sqlite3_errcode(db_user));
return -1;
}
printf("sqlite3_open success\n");
//创建表
char create_db_shell[128] = "create table if not exists usr (name char, passward char)";
if (sqlite3_exec(db_user, create_db_shell, NULL, NULL, NULL) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_exec : %s errcode : %d\n", sqlite3_errmsg(db_user), sqlite3_errcode(db_user));
return -1;
}
printf("create teble success\n");
if (sqlite3_open("./dict.db", &db) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open : %s errcode : %d\n", sqlite3_errmsg(db), sqlite3_errcode(db));
return -1;
}
printf("sqlite3_open success\n");
//创建用户数据库
if (sqlite3_open("./history.db", &db_history) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open : %s errcode : %d\n", sqlite3_errmsg(db_history), sqlite3_errcode(db_history));
return -1;
}
printf("sqlite3_open success\n");
//创建表
char create_db_shell_his[128] = "create table if not exists history (name char, ENGLISH char, CHINESE char)";
if (sqlite3_exec(db_history, create_db_shell_his, NULL, NULL, NULL) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_exec : %s errcode : %d\n", sqlite3_errmsg(db_history), sqlite3_errcode(db_history));
return -1;
}
printf("create history teble success\n");
//多进程并发框架
pthread_t tid_cli_deal;
int newfd = -1;
struct sockaddr_in cin;
socklen_t cin_len = sizeof(cin);
struct cin_info cin_information;
while (1)
{
//初始化
//memset(&cin_information, 0, sizeof(cin_information));
newfd = accept(sfd, (struct sockaddr*)&cin, &cin_len);
if (newfd < 0)
{
ERR_MSG("accept");
return -1;
}
//将客户端信息填充到结构体中
cin_information.cin = cin;
cin_information.newfd = newfd;
if (pthread_create(&tid_cli_deal, NULL, cin_deal, &cin_information) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
}
close(sfd);
return 0;
}
//线程回调处理客户端需求函数
void* cin_deal(void* arg)
{
struct cin_info user_cin = *(struct cin_info*)arg;
struct message cin_message;
memset(&cin_message, 0, sizeof(struct message));
int res = 0;
while (1)
{
res = recv(user_cin.newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("recv");
break;
}
switch (cin_message.type)
{
case 'L':
do_loin(cin_message, &user_cin);
break;
case 'R':
do_region(cin_message, &user_cin);
break;
case 'S':
do_search(cin_message, &user_cin);
break;
case 'H':
do_history(cin_message, &user_cin);
break;
default:
memset(&cin_message, 0, sizeof(cin_message));
printf("数据错误\n");
continue;
}
}
close(user_cin.newfd);
}
int do_login(struct message cin_message, struct cin_info* user_cin)
{
//遍历数据库查询登录信息是否正确
int flag = 0; //用于判断是否登录成功 0失败 1成功
char sql[128] = "select * from usr;";
char** pres = NULL;
int row, column;
char* errmsg = NULL;
int res = -1;
if(sqlite3_get_table(db_user, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
//默认账号错误,密码错误会覆盖"passward error\n",查询成功会覆盖上中文翻译
strcpy(cin_message.chinese, "name of user error\n");
for(int i=0; i<(row+1)*column; i++)
{
if (i%2 == 0 || i == 0)
{
if (strcmp(cin_message.name, pres[i]) == 0 )
{
if (strcmp(cin_message.passward, pres[i+1]) == 0)
{
flag = 1;
cin_message.type = 'l';
strcpy(cin_message.chinese, pres[i+1]);
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
else
{
strcpy(cin_message.chinese, "passward error\n");
break;
}
}
}
}
if (0 == flag)
{
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
int do_region(struct message cin_message, struct cin_info* user_cin)
{
//遍历数据库查询用户名是否有重复
int flag = 1; //用于判断是否查询成功 0注册失败 1注册成功
char sql[128] = "select name from usr;";
char** pres = NULL;
int row, column;
char* errmsg = NULL;
if(sqlite3_get_table(db_user, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
int index = 0;
int res = -1;
for(int i=0; i<(row+1); i++)
{
for(int j=0; jnewfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
index++;
}
}
if (1 == flag)
{
//账号没重复,可以注册
//填充用户信息到数据库
char sql[128] = "";
sprintf(sql,"insert into usr values(\"%s\", \"%s\");", cin_message.name, cin_message.passward);
printf("sql=%s __%d__\n", sql, __LINE__);
char* errmsg = NULL;
if(sqlite3_exec(db_user, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
printf("insert into usr success\n");
//回复客户端
cin_message.type = 'r';
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
int do_search(struct message cin_message, struct cin_info* user_cin)
{
int res = 0;
char buf_search[64] = "";
strcpy(buf_search, cin_message.chinese);
struct message message_search;
//遍历词典
int flag = 0; //用于判断是否查询成功 0失败 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, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
for(int i=0; i<(row+1)*column; i++)
{
if (i%2 == 0 || i == 0)
{
if (strcmp(buf_search, pres[i]) == 0)
{
printf("找到 : %s\n", pres[i]);
flag = 1;
//插入历史记录
char sql[128] = "";
sprintf(sql,"insert into history values(\"%s\", \"%s\", \"%s\");", cin_message.name, cin_message.chinese, pres[i+1]);
printf("sql=%s __%d__\n", sql, __LINE__);
char* errmsg = NULL;
if(sqlite3_exec(db_history, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
printf("insert into history success\n");
//回复客户端
cin_message.type = 's';
strcpy(cin_message.chinese, pres[i+1]);
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
}
}
if (0 == flag)
{
//因为type没改变,所以客户端不会接收到s,直接发送原信息
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
int do_history(struct message cin_message, struct cin_info* user_cin)
{
char sql[128] = "select * from history;";
char** pres = NULL;
int row, column;
char* errmsg = NULL;
if(sqlite3_get_table(db_history, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
int index = 0;
int res = -1;
for(int i=0; i<(row+1)*column; i++)
{
if (i%3 == 0 || i == 0)
{
if (strcmp(cin_message.name, pres[i]) == 0)
{
strcpy(cin_message.english, pres[i+1]);
strcpy(cin_message.chinese, pres[i+2]);
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
}
}
//遍历结束,发送h
cin_message.type = 'h';
send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
2.服务端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg) do{\
perror(msg);\
printf("line: __%d__\n", __LINE__);\
}while(0);
#define IP_SER "192.168.8.66"
#define POST_SER 8888
//协议信息结构体
struct message
{
char type; //L:登录 R:注册 S:查询 H:查询历史信息
char name[16]; //l:登录成功 r:注册成功标志 s:返回查询成功 h:查询结束标志
char passward[16];
char chinese[64]; //中文意思 登录信息(登录失败原因:账号不存在或者密码错误)
char english[64];
};
//存储客户端对应的cin和fd的结构体,是线程创建的参数
struct cin_info
{
int newfd;
struct sockaddr_in cin;
};
//线程回调处理客户端需求函数
void* cin_deal(void* arg);
//switch分支函数
int do_login(struct message cin_message, struct cin_info* user_cin);
int do_region(struct message cin_message, struct cin_info* user_cin);
int do_search(struct message cin_message, struct cin_info* user_cin);
int do_history(struct message cin_message, struct cin_info* user_cin);
int do_select();
//记录用户账号密码的数据库权柄
sqlite3* db_user = NULL;
//电子词典的数据库权柄
sqlite3* db = NULL;
//历史记录的数据库权柄
sqlite3* db_history = NULL;
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket success sfd = %d\n", sfd);
int reuse = 1;
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口重用\n");
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(POST_SER);
sin.sin_addr.s_addr = inet_addr(IP_SER);
if (bind(sfd, (struct sockaddr*)&sin, (socklen_t)sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
if(listen(sfd, 128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
//创建用户数据库
if (sqlite3_open("./user.db", &db_user) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open : %s errcode : %d\n", sqlite3_errmsg(db_user),
sqlite3_errcode(db_user));
return -1;
}
printf("sqlite3_open success\n");
//创建表
char create_db_shell[128] = "create table if not exists usr (name char, passward
char)";
if (sqlite3_exec(db_user, create_db_shell, NULL, NULL, NULL) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_exec : %s errcode : %d\n", sqlite3_errmsg(db_user),
sqlite3_errcode(db_user));
return -1;
}
printf("create teble success\n");
if (sqlite3_open("./dict.db", &db) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open : %s errcode : %d\n", sqlite3_errmsg(db),
sqlite3_errcode(db));
return -1;
}
printf("sqlite3_open success\n");
//创建用户数据库
if (sqlite3_open("./history.db", &db_history) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_open : %s errcode : %d\n", sqlite3_errmsg(db_history),
sqlite3_errcode(db_history));
return -1;
}
printf("sqlite3_open success\n");
//创建表
char create_db_shell_his[128] = "create table if not exists history (name char,
ENGLISH char, CHINESE char)";
if (sqlite3_exec(db_history, create_db_shell_his, NULL, NULL, NULL) != SQLITE_OK)
{
fprintf(stderr, "sqlite3_exec : %s errcode : %d\n", sqlite3_errmsg(db_history),
sqlite3_errcode(db_history));
return -1;
}
printf("create history teble success\n");
//多进程并发框架
pthread_t tid_cli_deal;
int newfd = -1;
struct sockaddr_in cin;
socklen_t cin_len = sizeof(cin);
struct cin_info cin_information;
while (1)
{
//初始化
//memset(&cin_information, 0, sizeof(cin_information));
newfd = accept(sfd, (struct sockaddr*)&cin, &cin_len);
if (newfd < 0)
{
ERR_MSG("accept");
return -1;
}
//将客户端信息填充到结构体中
cin_information.cin = cin;
cin_information.newfd = newfd;
if (pthread_create(&tid_cli_deal, NULL, cin_deal, &cin_information) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
}
close(sfd);
return 0;
}
//线程回调处理客户端需求函数
void* cin_deal(void* arg)
{
struct cin_info user_cin = *(struct cin_info*)arg;
struct message cin_message;
memset(&cin_message, 0, sizeof(struct message));
int res = 0;
while (1)
{
res = recv(user_cin.newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("recv");
break;
}
switch (cin_message.type)
{
case 'L':
do_loin(cin_message, &user_cin);
break;
case 'R':
do_region(cin_message, &user_cin);
break;
case 'S':
do_search(cin_message, &user_cin);
break;
case 'H':
do_history(cin_message, &user_cin);
break;
default:
memset(&cin_message, 0, sizeof(cin_message));
printf("数据错误\n");
continue;
}
}
close(user_cin.newfd);
}
int do_login(struct message cin_message, struct cin_info* user_cin)
{
//遍历数据库查询登录信息是否正确
int flag = 0; //用于判断是否登录成功 0失败 1成功
char sql[128] = "select * from usr;";
char** pres = NULL;
int row, column;
char* errmsg = NULL;
int res = -1;
if(sqlite3_get_table(db_user, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
//默认账号错误,密码错误会覆盖"passward error\n",查询成功会覆盖上中文翻译
strcpy(cin_message.chinese, "name of user error\n");
for(int i=0; i<(row+1)*column; i++)
{
if (i%2 == 0 || i == 0)
{
if (strcmp(cin_message.name, pres[i]) == 0 )
{
if (strcmp(cin_message.passward, pres[i+1]) == 0)
{
flag = 1;
cin_message.type = 'l';
strcpy(cin_message.chinese, pres[i+1]);
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
else
{
strcpy(cin_message.chinese, "passward error\n");
break;
}
}
}
}
if (0 == flag)
{
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
int do_region(struct message cin_message, struct cin_info* user_cin)
{
//遍历数据库查询用户名是否有重复
int flag = 1; //用于判断是否查询成功 0注册失败 1注册成功
char sql[128] = "select name from usr;";
char** pres = NULL;
int row, column;
char* errmsg = NULL;
if(sqlite3_get_table(db_user, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
int index = 0;
int res = -1;
for(int i=0; i<(row+1); i++)
{
for(int j=0; jnewfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
index++;
}
}
if (1 == flag)
{
//账号没重复,可以注册
//填充用户信息到数据库
char sql[128] = "";
sprintf(sql,"insert into usr values(\"%s\", \"%s\");", cin_message.name, cin_message.passward);
printf("sql=%s __%d__\n", sql, __LINE__);
char* errmsg = NULL;
if(sqlite3_exec(db_user, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
printf("insert into usr success\n");
//回复客户端
cin_message.type = 'r';
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
int do_search(struct message cin_message, struct cin_info* user_cin)
{
int res = 0;
char buf_search[64] = "";
strcpy(buf_search, cin_message.chinese);
struct message message_search;
//遍历词典
int flag = 0; //用于判断是否查询成功 0失败 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, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
for(int i=0; i<(row+1)*column; i++)
{
if (i%2 == 0 || i == 0)
{
if (strcmp(buf_search, pres[i]) == 0)
{
printf("找到 : %s\n", pres[i]);
flag = 1;
//插入历史记录
char sql[128] = "";
sprintf(sql,"insert into history values(\"%s\", \"%s\", \"%s\");", cin_message.name, cin_message.chinese, pres[i+1]);
printf("sql=%s __%d__\n", sql, __LINE__);
char* errmsg = NULL;
if(sqlite3_exec(db_history, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
printf("insert into history success\n");
//回复客户端
cin_message.type = 's';
strcpy(cin_message.chinese, pres[i+1]);
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
}
}
if (0 == flag)
{
//因为type没改变,所以客户端不会接收到s,直接发送原信息
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}
int do_history(struct message cin_message, struct cin_info* user_cin)
{
char sql[128] = "select * from history;";
char** pres = NULL;
int row, column;
char* errmsg = NULL;
if(sqlite3_get_table(db_history, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
int index = 0;
int res = -1;
for(int i=0; i<(row+1)*column; i++)
{
if (i%3 == 0 || i == 0)
{
if (strcmp(cin_message.name, pres[i]) == 0)
{
strcpy(cin_message.english, pres[i+1]);
strcpy(cin_message.chinese, pres[i+2]);
res = send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
if (res < 0)
{
ERR_MSG("send");
return -1;
}
}
}
}
//遍历结束,发送h
cin_message.type = 'h';
send(user_cin->newfd, &cin_message, sizeof(cin_message), 0);
//释放查询到的结果的内存空间
sqlite3_free_table(pres);
pres = NULL;
return 0;
}