目录
前言
在线英英词典项目是一款基于网络的以单词查询为主要功能的软件,具体实现功能如下: 单词查询,账号注册与登录,历史记录管理
一、项目模块
1.网络通讯模块,服务器和客户端通基于 tcp 协议
2.数据持久化模块,使用轻量级数据库 SQLITE3
3.客户端菜单模块,使用命令行界面
二、实现步骤
1.服务器:使用sqlite3 数据库,在库中创建user表和record表(user 表,用于管理用户账号信息;record 表,用于管理历史查询信息);
2. 客户端:使用命令行界面来选择注册、登录、查询、历史记录、退出选项;
3.客户端选择注册:客户端输入账号密码,服务器接受数据后打开user表进行比对。如果user表中没有此用户则记录到表中,发送信息到客户端,客户端可继续选择登录账号;如果user表中有此用户则报错,发送信息到客户端,客户端重新注册账号;
4.客户端选择登录:客户端输入账号密码,服务器接受数据后打开user表进行比对,查看密码账号是否匹配。登录成功后可以进行查询;
5.客户端选择查询:客户端输入需要查询的单词,服务器接受单词后,打开dict.txt文档,如果没有该单词,则打印错误信息发送给客户端;如果该文档中有查询的单词,则发送该单词给客户端,并且记录此时的用户、时间和单词到record表中;
6.客户端选择查询历史记录:服务器接收到查询历史记录信息后,开始在record表中查询数据,每查到一条历史记录就给客户端发送一条记录,客户端也会一一接收;
三、功能代码
1.服务器 server.c
代码如下(示例):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <netinet/ip.h>
//信息结构体
typedef struct
{
char type; //选择
char name[64]; //用户名
char result[256]; // password密码 or word单词 or remark返回数据
} MSG_t;
//系统初始化的函数//打开数据文件、尝试建表
sqlite3 *process_init();
void recv_client(int rws, sqlite3 *sql_db);
void process_register(int rws, MSG_t *msg, sqlite3 *sql_db);
void process_login(int rws, MSG_t *msg, sqlite3 *sql_db);
void process_search(int rws, MSG_t *msg, sqlite3 *sql_db);
void sigHandler(int signo);
int server_init(char *ipaddr, unsigned short port, int backlog);
int get_time(char *time_s);
void process_history(int rws, MSG_t *msg, sqlite3 *sql_db);
int callback(void *arg, int ncolumn, char **f_value, char **f_name);
int main(int argc, char *argv[])
{
if(argc < 3)
{
printf("Usage:%s <ip> <port>\n",argv[0]);
return -1;
}
//数据库初始化
sqlite3 *sql_db = process_init();
//signal(SIGCHLD, sigHandler);
int sockfd = server_init(argv[1], atoi(argv[2]), 1024);
if(-1 == sockfd)
{
printf("server_init error\n");
return -1;
}
printf("listen....\n");
struct sockaddr_in caddr;//保存客户端的信息(ip port protocol)
bzero(&caddr, sizeof(caddr));
socklen_t clen = sizeof(caddr);
int ret;
while(1)
{
//rws:用于服务器和连接的客户端通信
int rws = accept(sockfd, (struct sockaddr *)&caddr, &clen);//阻塞等待客户端请求连接
if(-1 == rws)
{
perror("accept");
close(sockfd);
return -1;
}
printf("IP:%s Port:%u\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
//创建子进程
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
break;
}
else if(0 == pid)//子进程
{
close(sockfd);//关闭监听套接字
recv_client(rws, sql_db