TCP电子词典

common.h

#ifndef __COMMON_H__
#define __COMMON_H__
 
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
 
#define   N  32
typedef struct {
	int type;
	char name[N];
	char data[256];
	int option;
	int flag;
}MSG;
 
#define  R  1   // user - register
#define  L  2   // user - login
#define  Q  3   // user - query
#define  H  4   // user - history
 
#define  DATABASE  "my.db" //创建的数据库
 
 
#define SERADDR "127.0.0.1"   
#define SERPORT 5001          
 
#endif

服务器

#include "common.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;
		}
	printf("[%s:%d]连接到服务器..\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
		if((pid = fork()) < 0)
		{
			perror("fail to fork");
			return -1;
		}
		else if(pid == 0)  
		{//son process
			close(sockfd);
			do_client(acceptfd, db);

		}
		else  
		{//father process

			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("client exit.\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
	{
		if (strcmp("no", result[5]) == 0)
		{
			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);
		}
		else
		{
			strcpy(msg->data, "不允许重复登录\n");
			msg->flag = 0;
		}
	}

	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, "query end");
	send(acceptfd, info, sizeof(info), 0);
	return 1;
}
//int history_callback(void* arg,int f_num,char** f_value,char** f_name);//查询历史函数使用的回调
//int do_searchword(int acceptfd, MSG *msg, char word[]);//查询单词函数的回调
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 "common.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("* 1.register          2.login              3.quit               *\n");
		printf("*****************************************************************\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("Invalid data cmd.\n");
		}
 
 
	}
	return 0;
}
 
int SubMenu(int sockfd)
{
	int n;
	MSG  msg;
 
	while(1)
	{
		printf("-----------------------------------------------------\n");
		printf("- 1.query_word   2.history_record   3.quit          -\n");
		printf("-----------------------------------------------------\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("请输入单词 (输入#退出): ");
        scanf("%s", msg->data);
        while (getchar() != 10)
            ;
        //如果输入的是#,返回
        if (strcmp(msg->data, "#") == 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, "query end"))
        {
            break;
        }
    }
    return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值