网络编程项目:电子辞典

项目要求:

  1. 登录注册功能,不能重复登录,重复注册。用户信息也存储在数据库中。
  2. 单词查询功能
  3. 历史记录功能,存储单词,意思,以及查询时间,存储在数据库
  4. 基于TCP,支持多客户端连接(多进程、多线程、多路复用)
  5. 采用数据库保存用户信息与历史记录
  6. 将dict.txt的数据导入到数据库中保存。
  7. 返回上级、按下ctrl+c退出客户端后,该客户端退出登录

网络编程项目:电子辞典_第1张图片

网络编程项目:电子辞典_第2张图片

server.c

int do_register(int sockfd, MSG_T *msg, sqlite3 *db);
int do_login(int sockfd, MSG_T *msg, sqlite3 *db);
int do_searchword(MSG_T *msg, char *word);
int do_query(int sockfd, MSG_T *msg, sqlite3 *db);
int history_callback(void *arg, int colCount, char **colValue, char **colName);
int do_history(int sockfd, MSG_T *msg, sqlite3 *db);
int do_client(int acceptfd, sqlite3 *db);

int main(int argc, const char *argv[])
{
	int sockfd, acceptfd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	socklen_t addrlen = sizeof(client_addr);
	char ip_addr[16]; //存放ip地址
	sqlite3 *db = NULL;
	char *errmsg = NULL;
	char sql[1024] = "";
	pid_t pid;

	//数据库操作
	if (sqlite3_open(DATABASE, &db) != SQLITE_OK) //打开数据库
	{
		printf("%s\n", sqlite3_errmsg(db));
		return -1;
	}
	sprintf(sql, "create table if not exists user(name text primary key, passwd text);");
	if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) //创建用户表
	{
		printf("%s\n", errmsg);
		return -1;
	}
	memset(sql, 0, sizeof(sql));
	sprintf(sql, "create table if not exists record(name text, date text, word text);");
	if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) //创建记录表
	{
		printf("%s\n", errmsg);
		return -1;
	}

	// 申请socket
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("fail to socket\n");
		return -1;
	}

	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr("192.168.3.107");
	server_addr.sin_port = htons(8888);
	bzero(&(server_addr.sin_zero), sizeof(server_addr.sin_zero));

	//绑定套接字
	if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
	{
		perror("bind error\n");
		return -1;
	}

	//将套接字设为监听模式
	if (listen(sockfd, 5) < 0)
	{
		perror("listen error\n");
		exit(1);
	}
	printf("listen success.\n");

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

	while (1)
	{
		//接收客户端的连接请求
		if ((acceptfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen)) < 0)
		{
			perror("accept error\n");
			return -1;
		}
		if (inet_ntop(AF_INET, &client_addr.sin_addr, ip_addr, addrlen) < 0)
		{
			perror("inet_ntop error\n");
			return -1;
		}
		printf("client(%s:%d) is connected!\n", ip_addr, htons(client_addr.sin_port));

		//创建子进程
		if ((pid = fork()) < 0)
		{
			perror("fork error\n");
			return -1;
		}
		else if (pid == 0) //子进程,处理客户端请求
		{
			close(sockfd);
			do_client(acceptfd, db);
		}
		else //父进程,用来接收客户端的连接请求
		{
			close(acceptfd); 
		}
	}

	return 0;
}

client.c

int do_register(int sockfd, MSG_T *msg)
int do_login(int sockfd, MSG_T *msg)
int do_query(int sockfd, MSG_T *msg)
int do_history(int sockfd, MSG_T *msg)
int main(int argc, const char *argv[])
{
	int sockfd;
	struct sockaddr_in server_addr;
	int input_nbr;
	MSG_T send_msg;
	// 申请socket
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket error\n");
		return -1;
	}	
	
	server_addr.sin_family  = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr("192.168.3.107");
	server_addr.sin_port = htons(8888);
    bzero(&(server_addr.sin_zero), sizeof(server_addr.sin_zero));
    
    //连接服务器
    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) < 0)
	{
		perror("connect error\n");
		return -1;
	}
	
	while (1)
	{
		printf("***********************************************\n");
		printf("\t  1.注册   2.登录   3.退出  \n");
		printf("***********************************************\n");
		printf("请选择功能:");
		
		scanf("%d", &input_nbr);
		getchar();//回收垃圾字符
		
		// 一级菜单
		switch (input_nbr)
		{
			case 1:
				do_register(sockfd, &send_msg);
				break;
			case 2:
				if (do_login(sockfd, &send_msg) == 1)
				{
					goto _login;
				}
				break;	
			case 3:
				close(sockfd);
				exit(0);
				break;
			default:
				printf("请输入正确的选项 \n");
				break;
		}
	}
	//二级菜单,登录后进行单词查询
_login:
	while(1)
	{
		system("clear");
		printf("***********************************************\n");
		printf("\t   1.查询单词  2.历史查询  3.退出\n");
		printf("***********************************************\n");
		printf("请选择功能:");
		
		input_nbr = 0;
		scanf("%d", &input_nbr);
		getchar();//回收垃圾字符

		switch (input_nbr)
		{
			case 1:
				do_query(sockfd, &send_msg);
				break;
			case 2:
				do_history(sockfd, &send_msg);
				break;
			case 3:
				close(sockfd);
				exit(0);
				break;
			default:
				printf("input_nbr error\n");
				break;
		}
	}
	return 0;
}

你可能感兴趣的:(网络,oracle,数据库)