项目——电子词典

项目和格式要求

项目要求:
1. 登录注册功能,不能重复登录,重复注册
2. 单词查询功能
3. 历史记录功能,存储单词,意思,以及查询时间
4. 基于TCP,支持多客户端连接
5. 采用数据库保存用户信息与历史记录
6. 将dict.txt的数据导入到数据库中保存。
7. 按下ctrl+c退出客户端后,注销该客户端的登录信息
格式要求:
1. main函数只跑逻辑,不允许

流程图

在这里插入图片描述

代码

function.h

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

//打印新的错误宏函数
#define ERR_MSG(msg)	do{\
	fprintf(stderr, "__%d__", __LINE__);\
	perror(msg);\
}while(0)

#define PORT 8888
#define IP "192.168.239.128"

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

//主菜单
void menu();

//登录子菜单
void logon_menu();

//登录
int logon(int sfd);

//注册
int regis(int sfd);

//单词查询
int word(int sfd);

//历史记录
int history(int sfd);

//用户下线
int notlogin(sqlite3 *db, char *user);

//数据库初始化
sqlite3 *init_db();

//服务器客户端交互
int interact(int newfd, sqlite3 *db, struct sockaddr_in cli);

#endif

function.c

#include "function.h"
//主菜单
void menu()			
{
	printf("—————————————————\n");
	printf("1、登录\n");
	printf("2、注册\n");
	printf("0、退出\n");
	printf("—————————————————\n");
	printf("请输入序号:");
}

//登录子菜单
void logon_menu()			
{
	printf("—————————————————\n");
	printf("1、单词查找\n");
	printf("2、历史记录\n");
	printf("0、退出登录\n");
	printf("—————————————————\n");
	printf("请输入序号:");
}

//登录
int logon(int sfd)			
{
	char user[18];
	char pass[18];
	char request[128];
	char choose;
	ssize_t res;
	printf("请输入用户名:");
	fgets(user, sizeof(user), stdin);
	user[strlen(user)-1] = 0;
	printf("请输入密码:");
	fgets(pass, sizeof(pass), stdin);
	pass[strlen(pass)-1] = 0;

	//发送登录请求给服务器
	sprintf(request, "%c%c%s%c%s%c", 'L', 0, user, 0, pass, 0);
	if(send(sfd, request, 2+strlen(user)+1+strlen(pass)+1, 0) < 0)
	{
		ERR_MSG("send");
		return -1;
	}
	//接收服务返回的信息
	bzero(request, sizeof(request));
	res = recv(sfd, request, sizeof(request), 0);
	if(res < 0)
	{
		ERR_MSG("recv");
		return -1;
	}
	else if(0 == res)
	{
		printf("服务器已关闭\n");
		return -1;
	}

	printf("%s\n", request);

	//接收服务器发来的应答
	if(request[0] == 'Y')
	{
		printf("登录成功\n");

		//进入登录子菜单
		while(1)
		{
			logon_menu();
			scanf("%c", &choose);
			while(getchar()!=10);
			switch(choose)
			{
				case '1':
					{
						//单词查询
						word(sfd);
						break;
					}
				case '2':
					{
						//历史记录
						history(sfd);
						break;
					}
				case '0':
					{
						//退出登录并向服务器发送下线请求
						//向服务器发送下线信息
						sprintf(request, "%c%c%s%c", 0, 'Q', user, 0);
						if(send(sfd, request, 2+strlen(user)+1, 0) < 0)
						{
							ERR_MSG("send");
							return -1;
						}
						break;

					}
				default:
					{
						printf("输入序号有误,请重新输入\n");
						break;
					}
			}
		}
	}
	else if(request[0] == 'N')
	{
		printf("登录失败,输入的账号或密码有误\n");
	}
	else if(request[0] == 'L')
	{
		printf(" 该账号已登录,请勿重复登录\n");
	}
	return 0;
}


//注册
int regis(int sfd)
{
	char user[18] = "";
	char pass[18] = "";
	char request[128] = "";
	ssize_t res = 0;

	printf("请输入用户名:");
	fgets(user, sizeof(user), stdin);
	user[strlen(user)-1] = 0;
	printf("请输入密码:");
	fgets(pass, sizeof(pass), stdin);
	pass[strlen(pass)-1] = 0;

	//向服务器发送注册请求
	sprintf(request, "%c%c%s%c%s%c", 'R', 0, user, 0, pass, 0);
	if(send(sfd, request, sizeof(request), 0) < 0)
	{
		ERR_MSG("send");
		return -1;
	}

	//接收服务返回的信息
	bzero(request, sizeof(request));	
	res = recv(sfd, request, sizeof(request), 0);
	if(res < 0)
	{
		ERR_MSG("recv");
		return -1;
	}
	else if(0 == res)
	{
		printf("服务器已关闭\n");
		return -1;
	}

	//接收服务器发来的应答
	if(request[0] == 'Y')
	{
		printf("注册成功!\n");
	}
	else if(request[0] == 'N')
	{
		printf("注册失败,该用户名已存在\n");
	}

	return 0;
}

//单词查询
int word(int sfd)
{
	char request[128] = "";
	char word[18] = "";
	ssize_t res;

	while(1)
	{
		printf("请输入要查询的单词:");
		bzero(word, sizeof(word));
		fgets(word, sizeof(word), stdin);
		word[strlen(word)-1] = 0;

		//向服务器发送查询单词的请求
		sprintf(request,"%c%c%s",'W', 0, word);
		if(send(sfd,request, 2+strlen(word)+1, 0) < 0)
		{
			ERR_MSG("send");
			return -1;
		}

		//接收服务器发来的应答
		bzero(request, sizeof(request));
		res = recv(sfd, request, 2, 0);
		if(res < 0)
		{
			ERR_MSG("recv");
			return -1;
		}
		else if(0 == res)
		{
			printf("服务器已关闭\n");
			return -1;
		}

		if(request[0] == 'Y')
		{
			while(1)
			{
				//给服务器发送应答
				bzero(request, sizeof(request));
				sprintf(request,"%c%c", 'Y', 0);
				if(send(sfd, request, 2, 0) < 0)
				{
					ERR_MSG("send");
					return -1;
				}

				//接收服务器发送过来的消息
				bzero(request, sizeof(request));
				res = recv(sfd, request, sizeof(request), 0);
				if(res < 0)
				{
					ERR_MSG("recv");
					return -1;
				}
				else if(0 == res)
				{
					printf("服务器已关闭\n");
					return -1;
				}
				if(request[0] == 'N')
				{
					//传输结束
					break;
				}
				//显示查询结果
				char *result = request+strlen(request)+1;
				printf("%-10s\t%-s\n", request, result);
			}
		}
		else if(request[0] == 'N')
		{
			printf("未找到该单词\n");
		}
	}
	return 0;
}

//查询历史记录
int history(int sfd)
{
	char request[128]="";
	ssize_t res;
	
	//向服务器发送查询历史记录请求
	sprintf(request,"%c%c",'H', 0);
	if(send(sfd, request, 2, 0) < 0)
	{
		ERR_MSG("send");
		return -1;
	}

	//接收服务返回的应答信息
	bzero(request, sizeof(request));
	res = recv(sfd, request, 2, 0);
	if(res < 0)
	{
		ERR_MSG("recv");
		return -1;
	}
	else if(0 == res)
	{
		printf("服务器已关闭\n");
		return -1;
	}
	
	if(request[0] == 'Y')
	{
		while(1)
		{
			bzero(request, sizeof(request));
			//给服务器发送应答
			sprintf(request, "%c%c",'Y', 0);
			if(send(sfd, request, 2, 0) < 0)
			{
				ERR_MSG("send");
				return -1;
			}
			//接收服务器发送过来的消息
			bzero(request, sizeof(request));
			res = recv(sfd, request, sizeof(request), 0);
			if(res<0)
			{
				ERR_MSG("recv");
				return -1;
			}
			else if(0 == res)
			{
				printf("服务器已关闭\n");
				return -1;
			}
			if(request[0] == 'N')
			{
				//传输完成
				break;
			}
			
			char *result = request+strlen(request)+1;
			char *time = result+strlen(result)+1;
			printf("%-18s%-30s\t%-16s\n", request, result, time);	
		}
	}
	else if(request[0] == 'N')
	{
		//历史记录
		printf("历史记录为空\n");
	}
	return 0;
}

//用户下线
int notlogin(sqlite3 *db, char *user)
{
	//将数据库中该用户状态信息更新为下线
	char sql[200] = "";
	char *errmsg = NULL;
	char **pres = NULL;    //存储查询结果的首地址
	int row = 0;             //查询结果的行数
	int column = 0;          //查询结果的列数

	//查询用户状态
	sprintf(sql,"select * from user where user=\"%s\" and state=%d;", user, 'L');
	if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
		return -1;
	}
	if(row == 1)
	{
		bzero(sql,sizeof(sql));
		sprintf(sql, "update user set state=%c where user='%s'", 'N', user);
		if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
		{
			fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__, sqlite3_errcode(db), errmsg);
			return -1;
		}
		printf("用户:%s 下线\n", user);
	}
	return 0;
}

sqlite3 *init_db()
{
	sqlite3 *db=NULL;
	//打开数据库
	if(sqlite3_open("./my.db", &db) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_open:%s\n", __LINE__,
				sqlite3_errmsg(db));
		return NULL;
	}
	//创建账户信息表格
	char sql[400] = "create table if not exists users (user char primary key,pass char,state char)";
	char* errmsg = NULL;
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__,errmsg);
		return NULL;
	}
	//创建历史记录表格
	sprintf(sql,"create table if not exists record (user char,word char,mean char,time char)");
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__,errmsg);
		return NULL;
	}

	
	//用户表全部更新为下线状态
	sprintf(sql, "update users set state=\"%c\" where state=\"%c\";", 'Q', 'L');
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
		return NULL;
	}
	

	printf("数据库初始化完成\n");

	return db;
}

//服务器客户端交互
int interact(int newfd, sqlite3 *db, struct sockaddr_in cli)
{
	char user[18] = "";					//用户名
	char pass[18] = "";					//密码
	char request[128] = "";				//客户端发来的请求
	char type;							//请求类型
	ssize_t res = 0;			
	while(1)
	{
		//接收客户端发送来的信息
		bzero(request, sizeof(request));
		res = recv(newfd, request,sizeof(request), 0);
		if(res < 0)
		{
			ERR_MSG("recv");
			return -1;
		}
		else if(0 == res)
		{
			notlogin(db,user);
			printf("[IP:%s 端口:%d]断开连接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
			return -1;
		}

		//拆解请求
		type = request[0];
		//printf("%c\n", type);
		switch(type)
		{
		case 'L':
			{
				//登录信息
				bzero(user, sizeof(user));
				strcpy(user, request+2);					//用户名
				strcpy(pass, request+2+strlen(user)+1);		//密码

				//查询数据库中是否存在该用户
				char sql[200] = "";
				char **pres = NULL;    //存储查询结果的首地址
				int row = 0;             //查询结果的行数
				int column = 0;          //查询结果的列数
				char *errmsg = NULL;
				sprintf(sql, "select * from users where user=\"%s\" and pass =\"%s\"", user, pass);
				if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr,"__%d__ sqlite3_get_table:%s\n",__LINE__,errmsg);
					return -1;
				}
				if(row == 1)
				{
					//存在该用户名
					//判断密码是否正确
					//判断是否重复登录
					sprintf(sql,"select * from users where user=\"%s\" and pass=\"%s\" and state=\"%c\";",user,pass,'Q');			
					if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
					{
						fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
						return -1;
					}

					if(row == 1)
					{
						//发送信息给客户端
						bzero(request, sizeof(request));
						sprintf(request, "%c%c", 'Y', 0);
				//	  	printf("%s\n", request);
						if(send(newfd, request, 2, 0) < 0)
						{
							ERR_MSG("send");
							return -1;
						}
						//更新用户状态为上线
						bzero(sql, sizeof(sql));
						sprintf(sql, "update users set state=\"%c\" where user='%s'", 'L', user);
						if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
						{
							fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
							return -1;
						}
						printf("用户:%s 已上线\n",user);
					}
					else
					{
						//发送已登录消息给客户端
						bzero(request, sizeof(request));
						sprintf(request,"%c%c", 'L', 0);
			//			printf("%s\n", request);
						if(send(newfd, request, 2, 0) < 0)
						{
							ERR_MSG("send");
							return -1;
						}
					}
				}
				else
				{
					//用户名不存在或密码错误
					//发送登录失败信息给客户端
					bzero(request, sizeof(request));
					sprintf(request, "%c", 'N', 0);
			//		printf("%s\n", request);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
				}
				//释放获取到的空间
				sqlite3_free_table(pres);
				pres = NULL;
			}
			break;
		case 'R':
			{
				//注册信息
				bzero(user,sizeof(user));
				strcpy(user, request+2);
				strcpy(pass, request+2+strlen(user)+1);

				//查询数据库中是否存在该用户名
				char sql[200]="";
				char **pres = NULL;    //存储查询结果的首地址
				int row=0;             //查询结果的行数
				int column=0;          //查询结果的列数
				char *errmsg = NULL;
				sprintf(sql,"select * from users where user=\"%s\";",user);
				if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
					return -1;
				}

				if(row != 1)
				{
					//发送可注册信息给客户端
					bzero(request, sizeof(request));
					sprintf(request, "%c%c", 'Y', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
					//将注册信息写入到数据库
					bzero(sql, sizeof(sql));
					sprintf(sql, "insert into users values(\"%s\", \"%s\",\"%c\")", user, pass, 'Q');
					if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
					{
						fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
						return -1;
					}
					printf("用户:%s 信息已存入数据库\n",user);
				}
				else
				{
					//用户名已存在
					//发送无法注册信息给客户端
					bzero(request, sizeof(request));
					sprintf(request, "%c%c", 'N', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
				}

				//释放获取到的空间
				sqlite3_free_table(pres);
				pres = NULL;
			}
			break;
		case 'W':
			{
				//查询单词信息
				char word[18] = "";
				char result[18] = "";
				strcpy(word, request+2);

				//查询数据库中是否存在该单词
				char sql[200] = "";
				char **pres = NULL;    //存储查询结果的首地址
				int row = 0;             //查询结果的行数
				int column = 0;          //查询结果的列数
				char *errmsg = NULL;
				sprintf(sql, "select * from dict where word=\"%s\";", word);
				if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
					return -1;
				}

				if(row > 0)
				{
					//存在该单词
					bzero(request,sizeof(request));
					sprintf(request,"%c%c", 'Y', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
					//接收客户端发送来的应答
					bzero(request, sizeof(request));
					res = recv(newfd, request, 2, 0);
					if(res < 0)
					{
						ERR_MSG("recv");
						return -1;
					}
					else if(0 == res)
					{
						notlogin(db, user);
						printf("[IP:%s 端口:%d]断开连接\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
						return -1;
					}

					int i;
					bzero(request, sizeof(request));
					for(i=column; i<(row+1)*column; i++)
					{
						if(i%column == 0)
						{
							//获取单词
							bzero(word,sizeof(word));
							sprintf(word, "%s", pres[i]);
							strcpy(request, word);
						}
						if(i%column == (column-1))
						{
							//获取单词意思
							bzero(result, sizeof(result));
							sprintf(result, "%s", pres[i]);
							strcpy(request+strlen(word)+1, result);
							
							if(send(newfd, request, 2+strlen(word)+strlen(result)+1, 0) < 0)
							{
								ERR_MSG("send");
								return -1;
							}
							//获取查询时间
							time_t t = 0;
							struct tm *info = NULL;
							char record_time[18] = "";
							t = time(NULL);    
							info = localtime(&t);
							sprintf(record_time,"%d-%d-%d %d:%d",info->tm_year+1900,\
									info->tm_mon+1,info->tm_mday,info->tm_hour,\
									info->tm_min);
							//将查询记录输入到数据库
							bzero(sql,sizeof(sql));
							sprintf(sql, "insert into record values(\"%s\", \"%s\",\"%s\",\"%s\")",user,word, result, record_time);
							if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
							{
								fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
								return -1;
							}
							printf("用户:%s 查询已记录\n",user);
							//接收客户端发送来的应答
							bzero(request, sizeof(request));
							res = recv(newfd, request, sizeof(request), 0);
							if(res < 0)
							{
								ERR_MSG("recv");
								return -1;
							}
							else if(0 == res)
							{
								notlogin(db, user);
								printf("[IP:%s 端口:%d]断开连接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
								return -1;
							}
						
							if(request[0] == 'Y')
							{
								bzero(request,sizeof(request));
							}
							else if(request[0] == 'N')
							{
								printf("传输中断\n");
								break;
							}
						}
					}
					//传输完成
					printf("用户:%s 查询历史信息已传输\n",user);
					bzero(request, sizeof(request));
					sprintf(request, "%c%c", 'N', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
				}
				else
				{
					//不存在该单词
					bzero(request, sizeof(request));
					sprintf(request, "%c%c", 'N', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
				}
				//释放获取到的空间
				sqlite3_free_table(pres);
				pres = NULL;
			}
			break;
		case 'H':
			{
				//查询历史信息
				char record_time[18] = "";
				char word[18] = "";
				char result[18] = "";

				//查询该用户在数据库中是否存在记录
				char sql[200]="";
				char **pres = NULL;    //存储查询结果的首地址
				int row = 0;             //查询结果的行数
				int column = 0;          //查询结果的列数
				char *errmsg = NULL;
				sprintf(sql, "select * from record where user=\"%s\";", user);
				if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
					return -1;
				}
				if(row > 0)
				{
					//存在记录
					bzero(request, sizeof(request));
					sprintf(request, "%c%c", 'Y', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
					//接收客户端发送来的应答
					bzero(request, sizeof(request));
					res = recv(newfd, request, 2, 0);
					if(res < 0)
					{
						ERR_MSG("recv");
						return -1;
					}
					else if(0 == res)
					{
						notlogin(db,user);
						printf("[IP:%s 端口:%d]断开连接\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
						return -1;
					}

					int i;
					bzero(request, sizeof(request));
					for(i=column;i<(row+1)*column;i++)
					{
						if(i%column == (column-3))
						{
							//获取单词信息
							bzero(word, sizeof(word));
							sprintf(word, "%s", pres[i]);
							strcpy(request, word);
						}
						if(i%column == (column-2))
						{
							//获取单词意思
							bzero(result, sizeof(result));
							sprintf(result, "%s", pres[i]);
							strcpy(request+strlen(word)+1, result);
						}
						if(i%column == (column-1))
						{
							//获取时间信息
							bzero(record_time, sizeof(record_time));
							sprintf(record_time, "%s", pres[i]);

							//整合记录后发送给客户端
							strcpy(request+strlen(word)+strlen(result)+2, record_time);
							if(send(newfd, request, strlen(word)+strlen(result)+strlen(record_time)+3,0) < 0)
							{
								ERR_MSG("send");
								return -1;
							}
							//接收客户端发送来的应答
							bzero(request, sizeof(request));
							res = recv(newfd, request, sizeof(request), 0);
							if(res < 0)
							{
								ERR_MSG("recv");
								return -1;
							}
							else if(0 == res)
							{
								notlogin(db, user);
								printf("[IP:%s 端口:%d]断开连接\n",inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
								return -1;
							}
							if(request[0] == 'Y')
							{
								bzero(request, sizeof(request));
							}
							else if(request[0] == 'N')
							{
								printf("传输中断\n");
								break;
							}
						}
					}
					printf("用户:%s 查询历史信息已传输\n",user);
					bzero(request, sizeof(request));
					sprintf(request,"%c%c", 'N', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
				}
				else
				{
					//不存在记录
					bzero(request, sizeof(request));
					sprintf(request, "%c%c", 'N', 0);
					if(send(newfd, request, 2, 0) < 0)
					{
						ERR_MSG("send");
						return -1;
					}
				}
				//释放获取到的空间
				sqlite3_free_table(pres);
				pres = NULL;
			}
			break;
		case 'Q':
			{
				//处理下线信息
				strcpy(user, request+2);
				notlogin(db, user);
			}
			break;
		default:
			printf("未知信息\n");
		}
	}	
	return 0;
}

dictSer.c

#include "function.h"

typedef void (*sighandler_t)(int);

void handler(int sig)
{
	//回收僵尸进程
	while(waitpid(-1, NULL, WNOHANG) > 0);
}

int main(int argc, const char *argv[])
{
	int newfd = 0;
	pid_t pid = 0;
	sqlite3 *db = init_db();

	//捕获17号信号 SIGCHLD
	sighandler_t s = signal(17, handler);
	if(SIG_ERR == s)
	{
		ERR_MSG("signal");
		return -1;
	}

	//创建流式套接字
	int sfd = socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}

	//允许端口快速重用
	int reuse = 1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
	{
		ERR_MSG("setsocket");
		return -1;
	}

	//填写服务器地址信息结构体
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(PORT);
	ser.sin_addr.s_addr = inet_addr(IP);

	//绑定
	if(bind(sfd,(struct sockaddr *)&ser,sizeof(ser))!=0)
	{
		ERR_MSG("bind");
		return -1;
	}

	//监听
	if(listen(sfd,10)!=0)
	{
		ERR_MSG("listen");
		return -1;
	}

	//保存客户端的地址信息结构体
	struct sockaddr_in cli;
	socklen_t addrlen = sizeof(cli);

	while(1)
	{
		//父进程
		int newfd = accept(sfd,(struct sockaddr *)&cli,&addrlen);
		if(newfd<0)
		{
			ERR_MSG("accept");
			return -1;
		}
		pid = fork();
		if(pid>0)
		{
			close(newfd);
		}
		else if(0==pid)
		{
			close(sfd);

			//与客户端交互函
			interact(newfd,db,cli);
	
			//关闭
			close(newfd);
			exit(0);
		}
		else 
		{
			ERR_MSG("fork");
			return -1;
		}
	}

	//关闭数据库
	if(sqlite3_close(db) !=SQLITE_OK)
	{
		fprintf(stderr,"__%d__ sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
	}

	//关闭文件描述符
	close(sfd);

	return 0;
}

```c
#include "function.h"

int main(int argc, const char *argv[])
{
	char choose = 0;

	//创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}

	//填充要连接的服务器的地址信息结构体
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(PORT);
	ser.sin_addr.s_addr = inet_addr(IP);

	//连接服务器 connect
	if(connect(sfd, (struct sockaddr*)&ser, sizeof(ser)) < 0)
	{
		ERR_MSG("connect");
		return -1;
	}
	//主菜单
	while(1)
	{
		system("clear");
		menu();
		scanf("%c", &choose);
		while(getchar()!=10);
		switch(choose)
		{
		case '1':
			logon(sfd);
			break;
		case '2':
			regis(sfd);
			break;
		case '0':
			exit(0);
		default:
			printf("输入错误,请重新输入\n");
		}

	}
	//关闭套接字
	close(sfd);

	return 0;
}

```#include "function.h"

int main(int argc, const char *argv[])
{
	char choose = 0;

	//创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}

	//填充要连接的服务器的地址信息结构体
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(PORT);
	ser.sin_addr.s_addr = inet_addr(IP);

	//连接服务器 connect
	if(connect(sfd, (struct sockaddr*)&ser, sizeof(ser)) < 0)
	{
		ERR_MSG("connect");
		return -1;
	}
	//主菜单
	while(1)
	{
		system("clear");
		menu();
		scanf("%c", &choose);
		while(getchar()!=10);
		switch(choose)
		{
		case '1':
			logon(sfd);
			break;
		case '2':
			regis(sfd);
			break;
		case '0':
			exit(0);
		default:
			printf("输入错误,请重新输入\n");
		}

	}
	//关闭套接字
	close(sfd);

	return 0;
}

部分结果展示

注册
在这里插入图片描述
登录
在这里插入图片描述
单词查询
在这里插入图片描述
历史记录
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值