在线词典


https://blog.youkuaiyun.com/m0_37542524/article/details/85001614

应用综合项目

在线词典 简介

1,在线词典功能,分为客户端和服务器端
2,客户端有三个模块:注册、登录、查询(查询单词、查询历史记录)
3,服务器端要实现多并发服务器,这里采用多进程并发服务器:注册、登录、查询(查询单词、查询历史记录)
4,用户分为普通用户和管理员用户:管理员用户可以查询所有普通用户的历史记录,还可以看到词库中未定义的单词查询记录,普通用户只能查到自己的,词库中中有定义的记录
5,客户端和服务器通信只要通过一个信息结构体实现:

客户端 Client

框架

在这里插入图片描述

代码

/*
 *Client.c
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>


#define N 32
#define INIT_AVLUE   -1;

#define R  1  //用户-注册
#define L  2  //用户-登录
#define Q  3  //用户-查询
#define H  4  //用户-历史记录

#define USR 1 //普通用户
#define ROOT 2 //超级用户

//定义通信双方的信息结构体
typedef struct _msg
{
	int flag; //1:flag or 2:root
	int type; //用户名
	char name[N];
	char data[256]; //pwssword or word
} MSG;

typedef int  (*CallBackFunDiplay)(void * arg);
typedef int (*CallBackFunChoose)(int socketfd, MSG * msg);

typedef struct _display
{
	int result; //存储函数返回值的结果
	CallBackFunDiplay opt; //函数指针
} vDisplays;

typedef struct _functions
{
	int result;
	CallBackFunChoose opt;
} vFunctions;


// 函数声明
int Display_UserChoose(void *arg);
int Display_First_Menu(void *arg);
int Display_Second_Menu(void *arg);
int Init_Client(int *connfd, struct sockaddr_in *servaddr, const char* addr, const char *port);
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 do_close(int sockfd, MSG *arg );



int main(int argc, const char *argv[])
{
	int socketfd = INIT_AVLUE;
	struct sockaddr_in servaddr;
	int Input_Cmd;
	int Input_Cmd_Second;
	MSG  msg;
	vDisplays pDisplay;
	vFunctions pFunction;

	bzero(&msg, sizeof(msg));
	bzero(&pDisplay, sizeof(pDisplay));
	bzero(&pFunction, sizeof(pFunction));

	if (argc < 3)
	{
		printf("Input Error: %s <ip> <port>\n", argv[0]);
		return -1;
	}

	if (atoi(argv[2]) < 5000 )
	{
		printf("Input Port Error.\n");
		return -1;
	}

	if (Init_Client(&socketfd, &servaddr, argv[1], argv[2]) == -1)
	{
		printf("Fail:Init_Client.\n");
		return -1;
	}

	msg.flag = -1;

	do {
		pDisplay.opt = Display_UserChoose;
		pDisplay.result = pDisplay.opt(NULL);

		if (scanf("%d", &msg.flag) == 0)
			msg.flag = -1;
		while (getchar() != '\n');

		if (msg.flag != 1 && msg.flag != 2)
			msg.flag = -1;
	} while (msg.flag < 0);

	for (;;)
	{
		pDisplay.opt = Display_First_Menu;
		pDisplay.result = pDisplay.opt(NULL);

		Input_Cmd = -1;
		if (scanf("%d", &Input_Cmd)) {};
		getchar();

		switch (Input_Cmd)
		{
		case 1:
			pFunction.opt = do_register;
			pFunction.result = pFunction.opt(socketfd, &msg);
			break;
		case 2:
			pFunction.opt = do_login;
			if ((pFunction.result = pFunction.opt(socketfd, &msg)) == 1)
			{
				goto _NEXT;
			}
			break;
		case 3:
			pFunction.opt = do_close;
			pFunction.result = pFunction.opt(socketfd, NULL);
			exit(0);
			break;
		default:
			puts(" Input Error Number Cmd.");
			break;

		}
	}

_NEXT:

#if	1
	puts("NEXT");
#endif

	for (;;)
	{
		pDisplay.opt = Display_Second_Menu;
		pDisplay.result = pDisplay.opt(NULL);

		Input_Cmd_Second = -1;
		if (scanf("%d", &Input_Cmd_Second)) {};
		getchar();

		switch (Input_Cmd_Second)
		{
		case 1:
			pFunction.opt = do_query;
			pFunction.result = pFunction.opt(socketfd, &msg);

			break;

		case 2:
			pFunction.opt = do_history;
			pFunction.result = pFunction.opt(socketfd, &msg);
			break;

		case 3:
			pFunction.opt = do_close;
			pFunction.result = pFunction.opt(socketfd, NULL);
			exit(0);
			break;

		default:
			puts("Input Error Cmd.");
			break;
		}
	}

	return 0;

}

/**客户端:用户注册
 * 1.输入注册信息 用户名和密码
 *2.发送注册的信息给服务器
 *3.接收从服务器的反馈信息
 */ 
int do_register(int sockfd, MSG *msg)
{
	if (msg == NULL )
	{
		puts("do_register: msg parm NULL");
		return -1;
	}
	char passwd_str[32];
	int flag = -1;

	msg->type = R;

	//1.输入注册信息
	//
	printf("Input register name:");
	if (scanf("%s", msg->name)) {};
	getchar();

	do {

		printf("Input register password:");
		if (scanf("%s", passwd_str)) {};
		getchar();

		printf("Please Confirm  password:");
		if (scanf("%s", msg->data)) {};
		getchar();

		if (strlen(msg->data) == strlen(passwd_str))
		{
			if (strncmp(msg->data, passwd_str, strlen(passwd_str)) == 0)
			{
				flag = 1;
	
			}
			else
			{
				flag = -1;
				puts(" Error entering password ");
			}
		}
		else
		{
			puts("Error entering password");
			flag = -1;
		}
	} while (flag < 0);

	//2.发送
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("do_register:Send  Fail.\n");
		return -1;
	}
	printf("Client Send msg %s\n",msg->data);


	//接收
	if(recv(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		perror("do_register fail to recv");
		return -1;
	}

	if (strncasecmp(msg->data, "OK", strlen("OK")) == 0)
	{
		printf("Receive:register OK.\n");
		return 1;
	}	
	else
	{
		// user name 已经注册存在了
		printf("Receive: %s\n", msg->data);
	}


	return 0;
}
/**客户端:用户登录
 *1.输入登录信息 用户名和密码
 *2.发送注册的信息给服务器
 *3.接收从服务器的反馈信息
 */ 
int do_login(int sockfd, MSG *msg)
{
	if (msg == NULL)
	{
		puts("do_query: msg parm NULL ");
		return -1;
	}
	msg->type = L;

	//1.输入登录信息-用户
	printf("Input login name:");
	if (scanf("%s", msg->name)) {};
	getchar();

	//2.输入登录信息-密码
	printf("Input login  password:");
	if (scanf("%s", msg->data)) {};
	getchar();



	//2.发送
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Send Fail.\n");
		return -1;
	}

	//3.接收
	if(recv(sockfd, msg, sizeof(MSG), 0) < 0)	
	{
		printf("Receive Fail.\n");
		return -1;
	}
	
	//处理反馈消息
	if (strncmp(msg->data, "OK", strlen("OK")) == 0)
	{
		printf("Login OK.\n");
		return 1;
	}
	else
	{
		printf("%s\n", msg->data);
	}

	return 0;
}

/**客户端:用户查询
 *1.输入查询信息 word
 *2.发送查询信息给服务器
 *3.接收从服务器的反馈信息
 */ 
int do_query(int sockfd, MSG *msg)
{
	if (msg == NULL)
	{
		puts("do_query: msg parm NULL ");
		return -1;
	}
	msg->type = Q;

	while (1)
	{
		//1.输入查询信息
		printf("Input word: ( '#' exit )");
		if (scanf("%s", msg->data)) {};
		getchar();

		//客户端,输入#号,返回到上一级菜单
		if (strncmp(msg->data, "#", strlen("#")) == 0)
		{
			break;
		}

		//2.发送: 将要查询的单词发送给服务器
		if (send(sockfd, msg, sizeof(MSG), 0) < 0)
		{
			printf("Send Fail.\n");
			return -1;
		}

		//3.接收:等待接受服务器,传递回来的单词的注释信息
		if (recv(sockfd, msg, sizeof(MSG), 0) < 0)
		{
			printf("Receive Fail.\n");
			return -1;
		}

		//处理从服务器接受的信息
		printf("%s\n", msg->data);
	}

	return 0;
}
/**客户端: 历史记录查询
 *1.查询历史记录
 *2.发送查询信息给服务器
 *3.接收从服务器的反馈信息
 */ 

int do_history(int sockfd, MSG *msg)
{
	if (msg == NULL)
	{
		puts("do_history: msg parm NULL");
		return -1;
	}
	msg->type = H;

	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("do_history: Send Fail.\n");
		return -1;
	}

	// 接受服务器,传递回来的历史记录信息
	while (1)
	{
		if (recv(sockfd, msg, sizeof(MSG), 0) < 0)
		{
			printf("do_history: Receive Fail.\n");
			return -1;
		}
		//输出历史记录信息
	//	printf("%s\n", msg->data);

		if (msg->data[0] == '\0')
		{
			break;
		}

		printf("%s\n", msg->data);
	}
	return 0;
}

int do_close(int sockfd, MSG * arg)
{
	(void*)arg;

	close(sockfd);
	puts("Main exit");
}
/**
 *1. 建立socket(connfd)
 *2. 初始化服务器地址
 *3. socket向服务器发送请求,建立连接
 */
int Init_Client(int *socketfd, struct sockaddr_in *servaddr, const char* addr, const char *port)
{
	if ((*socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("fail to socket");
		return -1;
	}

	bzero(servaddr, sizeof(struct sockaddr_in));

	servaddr->sin_family = AF_INET;  			 //指定协议族
	servaddr->sin_port = htons(atoi(port));      //
	servaddr->sin_addr.s_addr  = inet_addr(addr);//

	if (connect(*socketfd,  (struct sockaddr*)servaddr, sizeof(struct sockaddr_in)) < 0)
	{
		perror("fail to connect.");
		return -1;
	}

	return 0;
}


int Display_UserChoose(void *arg)
{
	(void*)arg;

	puts("---------------------------------------------------");
	puts("-----  Select User Mode [ 1:user  2: root]    -----");
	puts("---------------------------------------------------");

	return 0;
}

int Display_First_Menu(void *arg)
{
	(void*)arg;

	puts("----------------------------------------------------");
	puts("-------------    Main Menu           ---------------");
	puts("----------- 1: New User Registrationu---------------");
	puts("------------2: User Login            ---------------");
	puts("------------3: User Quit             ---------------");
	puts("----------------------------------------------------");
	printf(" Please Input Select Number Function > \n");

	return 0;
}

int Display_Second_Menu(void *arg)
{
	(void*)arg;


	puts("----------------------------------------------------");
	puts("-------------    Second  Menu        ---------------");
	puts("----------- 1: Query World           ---------------");
	puts("------------2: Histroy Record        ---------------");
	puts("------------3: Quit                  ---------------");
	puts("----------------------------------------------------");
	printf(" Please Input Select Number Function > \n");

	return 0;
}

服务器端 Server

框架

在这里插入图片描述

代码

 /*
 *Server.c
 */


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h> 
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <sqlite3.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>


#define N 32
#define INIT_AVLUE   -1;
#define SIZE 128

#define R  1  //用户-注册
#define L  2  //用户-登录
#define Q  3  //用户-查询
#define H  4  //用户-历史记录

#define USR 1 //普通用户
#define ROOT 2 //超级用户

#define USE_DEBUG  1 //程序调试的宏 1 启动  0 失效

#define DATABASE "./table.db"

//定义通信双方的信息结构体
typedef struct _msg
{
	int flag; //1:flag or 2:root
	int type;
	char name[N];
	char data[256]; //pwssword or word
} MSG;

typedef struct _his
{
	int fd;
	MSG *msg;
}HIS_MSG;


typedef int (*CallBackFunChoose)(int socketfd, MSG * msg, sqlite3 *db);
typedef struct _functions
{
	int result;
	CallBackFunChoose opt;
} vFunctions;


// 函数声明

int do_client_handle(int newfd, struct sockaddr_in cin, sqlite3*db);
int Init_Server(int *listenfd, struct sockaddr_in *servaddr, const char* addr, const char *port);
int do_register(int sockfd, MSG *msg, sqlite3 *db);
int do_login(int sockfd, MSG *msg, sqlite3 *db);
int do_query(int sockfd, MSG *msg, sqlite3 *db);
int do_history(int sockfd, MSG *msg, sqlite3 *db);
int do_close(int sockfd, MSG *arg );
int do_create_table(sqlite3 *db);
const char *get_date(char * date);
int do_searchworld(MSG *msg);
int history_callback(void *his_msg, int f_num, char **f_value, char **f_name);



int main(int argc, const char *argv[])
{
	// 入口参数判断
	if (argc < 3)
	{
		printf("Input Error: %s <ip> <port>\n", argv[0]);
		return -1;
	}

	if (atoi(argv[2]) < 5000 )
	{
		printf("Input Port Error.\n");
		return -1;
	}

	sqlite3 *db;
	// 数据库存在则打开,不存在则创建 
	if(sqlite3_open(DATABASE,&db) != SQLITE_OK)
	{
		printf("%s\n", sqlite3_errmsg(db));
		return -1;
	}
	else
	{
		printf("open database:%s success.\n", DATABASE);
	}

	//表格不存在则创建数据库表格
	if(do_create_table(db) < 0)
	{
		//创建数据库表格失败
		return -1;
	}

	struct sockaddr_in servaddr;
	int socketfd = INIT_AVLUE;

	if (Init_Server(&socketfd, &servaddr, argv[1], argv[2]) == -1)
	{
		printf("Fail:Init_Serve");
		return -1;
	}

	signal(SIGCHLD, SIG_IGN); //处理僵尸进程

	pid_t pid;
	int status;
	int newfd = -1;
	struct sockaddr_in cliaddr; //客户端的信息
	socklen_t cliaddr_len = sizeof(cliaddr);

	while(1)
	{
		//阻塞等待客户端连接
		if ((newfd = accept(socketfd, (struct sockaddr *)&cliaddr, &cliaddr_len)) < 0)
		{
			perror("accept");
			return -1;

		}
		//连接从成功,创建子进程
		if ((pid = fork()) < 0)
		{
			perror("fork");
			return -1;

		}
		else if (pid == 0)
		{
			//子进程:处理客户端具体的消息
			close(socketfd);
			do_client_handle(newfd, cliaddr, db);		
		}
		else
		{
			//父进程:用来接受客户端的请求
			close(newfd);
			waitpid(-1, &status, WNOHANG);//以非阻塞方式回收当前进程的任意一个子进程

		}
	}

	return 0;
}

/*
 * 创建数据库表格
 */

int do_create_table(sqlite3 *db)
{
	char sql[SIZE];
	char **resultp;
	int nrow;
	int ncolumn;
	char *errmsg;

	//1:判断表格usr是否存在,不存在则创建 
	//
	sprintf(sql,"select * from sqlite_master where type='table' and name='usr';");
	sqlite3_get_table(db, sql, &resultp, &nrow, &ncolumn,&errmsg);
	
	if(nrow == 0)
	{
		// usr: name | permission | password
		sprintf(sql,"create table usr (name text primary key,permission integer, password txt);");

		if(sqlite3_exec(db, sql, NULL, NULL,&errmsg) != SQLITE_OK )
		{
			printf("create table:%s %s\n", "usr", errmsg);
			return -1;
		}
		else
		{
			puts("create table:usr success.");
		}
	}
	else
	{
		puts("table:usr is OK.");
	}


	//2:判断表格record是否存在,不存在则创建
	sprintf(sql,"select * from sqlite_master where type='table'and name='record';");
	sqlite3_get_table(db, sql, &resultp, &nrow, &ncolumn,&errmsg);
	if(nrow == 0)
	{
		//record: name | data | is_undefine
		sprintf(sql,"create table record (name text,data text,word text,is_undefine integer);");

		if (sqlite3_exec(db, sql, NULL, NULL,&errmsg) != SQLITE_OK)
		{
			printf("create table:%s %s\n", "record", errmsg);
			return -1;
		}
		else
		{
			puts("create table:record success.");
		}
	}
	else
	{
		puts("table:record is OK.");
	}

	return 0;
}
/*
 * 客户端消息处理
 */
int do_client_handle(int newfd, struct sockaddr_in cin, sqlite3*db)
{
	MSG msg;
	char ipv4_addr[16];
	int ret = -1;
	vFunctions pFunction;
	bzero(&pFunction, sizeof(pFunction));

	inet_ntop(AF_INET, (void *)&cin.sin_addr.s_addr, ipv4_addr, sizeof(cin));
	printf("client(ip:%s port:%d) is connected.\n", ipv4_addr, ntohs(cin.sin_port));

	while(1)
	{
		bzero(&msg, sizeof(msg));

		do{ 
			ret = recv(newfd, &msg, sizeof(msg),0);
		}while(ret < 0 && errno == EINTR);
		if(ret < 0)
		{
			perror("recv");
			close(newfd);
			return -1;
		}
		if(ret == 0) //客户端已关闭
		{
			break;
		}

		//根据类型执行操作
		printf("type:%d\n", msg.type);
		switch(msg.type)
		{
		case R:
			pFunction.opt = do_register;
			pFunction.result = pFunction.opt(newfd, &msg, db);
			break;
		case L:
			pFunction.opt = do_login;
			pFunction.result = pFunction.opt(newfd, &msg, db);
			break;

		case Q:
			pFunction.opt = do_query;
			pFunction.result = pFunction.opt(newfd, &msg, db);
			break;
		case H:
			pFunction.opt = do_history;
			pFunction.result = pFunction.opt(newfd, &msg, db);
			break;
		default:
			puts(" Input Error data msg");
			break;
		}
	}
	printf("client(ip:%s port:%d) exit.\n", ipv4_addr, ntohs(cin.sin_port));	
	close(newfd);
	exit(0);

	return 0;
}
/** 服务器:用户注册处理
 * 1.用户信息插入数据库表格中
 * 2.反馈消息给客户端
 */
int do_register(int sockfd, MSG *msg, sqlite3 *db)
{
	if (msg == NULL )
	{
		puts("do_register: msg parm NULL");
		return -1;
	}

	//将用户信息插入数据库表格usr(名字(主键),权限,密码
	char sql[SIZE];
	char *errmsg;

	sprintf(sql, "insert into usr values('%s',%d,'%s');",msg->name, msg->flag, msg->data);

	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		printf("do_register %s\n", errmsg);
		//插入失败说明用户名已存在
		strcpy(msg->data,"the usr already exit.");
	}
	else
	{
		printf("insert usr success.\n");
		strcpy(msg->data, "OK");
	}

	//反馈给客户端
	if(send(sockfd, msg, sizeof(MSG),0) < 0)
	{
		perror("do_register fail to send");
		return -1;
	}

#if  USE_DEBUG 	
	printf(" Server:(do_register)  send msg data  = %s\n",msg->data);
#endif	
	return 0;
}

/** 服务器:用户登录处理
 * 1.在数据库表格中查询登录用户信息
 * 2.反馈消息给客户端
 */
int do_login(int sockfd, MSG *msg, sqlite3 *db)
{
	if (msg == NULL)
	{	
		puts("do_login: msg parm NULL");
		return -1;
	}
	char sql[SIZE] = {};
	char *errmsg;
	int nrow;
	int ncloumn;
	char **resultp;

	//sql 查询登录的用户名
	sprintf(sql,"select * from usr where name = '%s';",msg->name);

	if(sqlite3_get_table(db, sql, &resultp, &nrow, &ncloumn, &errmsg) < 0)
	{
		printf("do_register %s", errmsg);
		return -1;
	}

	if (nrow == 0)// 密码或者用户名错误
	{
		printf("login name:%s does not exit.\n", msg->name);
		strcpy(msg->data, "the name does not exit.");
	}

	if(nrow == 1)
	{
		//用户存在: 查询成功,数据库中拥有此用户
		//判断:用户和权限匹配
		if(msg->flag == atoi(resultp[ncloumn + 1]))
		{
			//判断登录密码输入
			if (strncmp(msg->data, resultp[ncloumn + 2], strlen(msg->data)) == 0)
			{
				//密码输入正确
				printf("login success.\n");
				strcpy(msg->data, "OK");
			}
			else
			{
				//密码输入错误
				printf("login password is wrony.\n");
				strcpy(msg->data, "password is wrong.");
			}
		}
		//不匹配
		else if ( msg->flag != atoi(resultp[ncloumn + 1]))
		{
			printf("login usr permissions not match.\n");
			strcpy(msg->data, "usr permission not match.");
		}

	}

	//发送数据给客户端
	if(send(sockfd, msg, sizeof(MSG), 0) < 0 )
	{
		perror("do_login fail to send");
		return -1;
	}
	return 0;
}
/** 服务器:用户查询处理
 * 1.在单词库中寻找需要查询的单词
 * 2.反馈消息给客户端
 */
int do_query(int sockfd, MSG *msg ,sqlite3 *db)
{
	if (msg == NULL)
	{
		puts("do_query: msg parm NULL ");
		return -1;
	}

	char word[SIZE];
	int found = -1;
	char date[SIZE] = {};
	char sql[SIZE] = {};
	int is_undefine;
	char *errmsg = NULL;

	//获取本地时间
	get_date(date);

	//拿出msg结构体中,要查询的单词
	strcpy(word,msg->data);
	found = do_searchworld(msg);

	// 表示找到了单词,那么此时应该将 用户名,时间,单词,插入到历史记录表中去。
	if(found == 1)
	{
		// 0: 已有定义
		is_undefine = 0;
	}
	else if (found == 0)
	{
		// 1: 未定义
		is_undefine = 1;
	}

	//将查询信息发送给客户端:释义|The meaning of the word could not be  found|错误信息 
	if(send(sockfd,msg, sizeof(MSG), 0) < 0)
	{
		perror("do_query fail to send.");
		return -1;
	}

	// 一个单词查询完毕,服务端打印提示信息 
	printf("Word:%s query finished.\n", word);

	//将查询信息插入数据库表格record(名字,日期时间,单词,是否未定义)
	sprintf(sql,"insert into record values('%s','%s','%s','%d');",msg->name, date, word, is_undefine);

	if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		printf("do_query %s\n", errmsg);
		return -1;
	}
	return 0;
}
/** 服务器:历史记录查询处理
 * 1.在单词库中寻找需要查询的单词
 * 2.反馈消息给客户端
 */
int do_history(int sockfd, MSG *msg, sqlite3 *db)
{
	if (msg == NULL)
	{
		puts("do_history: msg parm NULL");
		return -1;
	}

	char sql[SIZE] = {};
	char *errmsg = NULL;
	HIS_MSG his_msg;

	//填充参数
	his_msg.fd = sockfd;
	his_msg.msg = msg;

	//判断用户权限 
	if(msg->flag == USR)
	{
		//普通用户
		sprintf(sql, "select * from record where name='%s' and is_undefine=%d;", msg->name, 0); 		
	}

	if (msg->flag == ROOT)
	{
		//ROOT用户
		sprintf(sql, "select * from record;");
	}

	/* 查询历史记录,执行回调函数 */
	if (sqlite3_exec(db, sql, history_callback, (void*)&his_msg, &errmsg) != SQLITE_OK)
	{
		printf("do_history %s\n", errmsg);
		return -1;
	}
	else
	{
		printf("Query history record successful.\n");
		/* 历史记录查询完了,给客户端发送查询完毕标志“\0” */
		strcpy(msg->data, "\0");

		if (send(sockfd, msg, sizeof(MSG), 0) < 0)
		{
			perror("do_history fail to send");
			return -1;
		}
		return 1;
	}

	return 0;
}

// 得到查询结果,并且需要将历史记录发送给客户端
int history_callback(void *his_msg, int f_num, char **f_value, char **f_name)
{
	HIS_MSG *h_msg = (HIS_MSG *)his_msg;
	
	if (h_msg->msg->flag == USR)
	{
		sprintf(h_msg->msg->data, "%s    %s", f_value[1], f_value[2]);
		printf("%s\n", h_msg->msg->data);
	}

	if (h_msg->msg->flag == ROOT)
	{
		sprintf(h_msg->msg->data, "%-20s%s    %-15s%s", f_value[0], f_value[1], f_value[2], f_value[3]);

	}

	if (send(h_msg->fd, h_msg->msg, sizeof(MSG), 0) < 0)
	{
		perror("history_callback fail to send");
		return -1;
	}

	return 0;
}
int do_close(int sockfd, MSG * arg)
{
	(void*)arg;

	close(sockfd);
	puts("Main exit");
}
/**
 *1. 建立socket(listenfd) 
 *2. 初始化服务器地址(servaddr)
 *3. socket与服务器地址绑定
 *4. 监听socket(listenfd)
 */
int Init_Server(int *socketfd, struct sockaddr_in *servaddr, const char* addr, const char *port)
{
	// 创建流式套接字 
	if ((*socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("fail to socket");
		return -1;
	}

	/* 允许绑定地址快速重用 */
	int b_reuse = 1;
	setsockopt(*socketfd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int));

	bzero(servaddr, sizeof(struct sockaddr_in));
	servaddr->sin_family = AF_INET;
	servaddr->sin_port = htons(atoi(port));
	servaddr->sin_addr.s_addr  = inet_addr(addr);
	//servaddr->sin_addr.s_addr = htonl(INADDR_ANY);// 让服务器可以绑定在任意的IP上

	//绑定
	if (bind(*socketfd,  (struct sockaddr*)servaddr, sizeof(struct sockaddr_in)) < 0)
	{
		perror("connect to fail.");
		return -1;
	}

	//监听
	if(listen(*socketfd, 5) < 0)
	{
		perror("fail to listen");
		return -1;
	}

	return 0;
}

//获取本地时间
const char *get_date(char * date) 
{
	time_t t;
	struct tm tp;

	time(&t);
	//进行时间格式转换
	tp = *localtime(&t);

	sprintf(date, "%04d-%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);
	return date;
}

//查询词典数据库文件dict.txt中的单词释义
int do_searchworld(MSG *msg)
{
	FILE *fp_r;
	int len;
	char str[512] = {};
	int result;
	char *p;


	//打开文件,读取文件,进行比对	
	if((fp_r = fopen("./dict.txt","r")) == NULL)
	{
		perror("do_searchworld fail to fopen");
		strcpy(msg->data,"Failed to open dict.txt" );		
		//发送错误消息
		return -1;
	}

	//打印需要查询的单词
	len = strlen(msg->data);
	printf("%s , len = %d\n", msg->data, len);

	//读文件,来查询单词
	while( fgets(str, 512, fp_r ) != NULL )
	{
		result = strncmp(str, msg->data, len);

		if(result < 0)
		{
			continue;
		}
		if(result > 0 ||  str[len] != ' ')
		{
			strcpy(msg->data, "The meaning of the word could not be found.\n");
			break;
		}

		// 表示找到了,查询的单词
		p = str + len;
		while(*p == ' ') //去掉单词释义前的空格
		{
			p++;
		}

		// 找到了注释,跳跃过所有的空格
		strcpy(msg->data, p);

		// 注释拷贝完毕之后,应该关闭文件
		fclose(fp_r);
		return 1;
	}

	fclose(fp_r);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值