网络编程项目:电子辞典

项目要求:

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

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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/382612.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leecode之反转链表

一.题目及剖析 https://leetcode.cn/problems/reverse-linked-list/description/ 二.思路引入 设定三个指针,n1指向空, n2指向head,n3指向下一个元素,将n2->next指向n1,然后三个指针向后遍历重复即可 三.代码引入 /*** Definition for singly-linked list.* struct List…

python从入门到精通(十六):python爬虫的BeautifulSoup4

python爬虫的BeautifulSoup4 BeautifulSoup4导入模块解析文件创建对象python解析器beautifulsoup对象的种类Tag获取整个标签获取标签里的属性和属性值Navigablestring 获取标签里的内容BeautifulSoup获取整个文档Comment输出的内容不包含注释符号BeautifulSoup文档遍历Beautifu…

Redis集群模型

主从 全量同步 增量同步 哨兵 分片集群

【Linux】 网络编程套接字

目录 预备知识 网络字节序 网络字节序和主机字节序转换的库函数 socket编程接口 socket常见API sockaddr结构 套接字的种类 预备知识 1.在IP数据包头部中&#xff0c;有两个IP地址&#xff0c;分别叫做源IP地址和目的IP地址。 2.端口号&#xff1a;是传输层协议的内容…

Mac 版 Excel 和 Windows 版 Excel的区别

Excel是一款由微软公司开发的电子表格程序&#xff0c;广泛应用于数据处理、分析和可视化等领域。它提供了丰富的功能和工具&#xff0c;包括公式、函数、图表和数据透视表等&#xff0c;帮助用户高效地处理和管理大量数据。同时&#xff0c;Excel还支持与其他Office应用程序的…

【动态规划】【回文】【字符串】1278分割回文串 III

作者推荐 【动态规划】【前缀和】【C算法】LCP 57. 打地鼠 本文涉及知识点 动态规划汇总 LeetCode1278分割回文串 III 给你一个由小写字母组成的字符串 s&#xff0c;和一个整数 k。 请你按下面的要求分割字符串&#xff1a; 首先&#xff0c;你可以将 s 中的部分字符修改…

vscode配置wsl ubuntu c++的环境

在ubuntu安装llvm/clang sudo apt install llvm clang clangd lldb vscode的调试器接口是按GDB开发的&#xff0c;所以需要一个适配器&#xff0c;lldb-mi就是这个适配器。lldb-mi原来是llvm项目的一部分&#xff0c;后面成为了一个单独的项目https://github.com/lldb-tools/…

【笔记】Harmony学习:下载安装 DevEco Studio 开发工具IDE

IDE 安装 从官网下载DevEco Studio 安装包后进行安装&#xff0c; 安装完毕后&#xff0c;本地环境可能要配置相关工具&#xff0c;可以通过下面的诊断检测一下本地环境&#xff0c;通过蓝色“Set it up now” 可以快速安装。 1. Node.js (for ohpm) 2. ohpm 下载op的包管理&a…

移动Web——响应式网页

响应式网页是指能够根据用户设备的屏幕大小、分辨率和浏览器窗口大小等因素自动调整布局和显示效果的网页设计方式。 通过使用响应式设计技术&#xff0c;网页可以在不同的设备上提供一致的用户体验&#xff0c;无论是在桌面电脑、平板电脑还是手机等移动设备上访问网页都能够适…

python 基础知识点(蓝桥杯python科目个人复习计划35)

今日复习计划&#xff1a;阶段总结&#xff08;新年贺礼&#xff09; 1.python简介&#xff08;定义&#xff0c;优点&#xff0c;缺点&#xff0c;应用领域&#xff09; python&#xff1a;一种广泛使用的解释型&#xff0c;高级和通用的编程语言 python极简&#xff0c;生…

【51单片机】串口通信实验(包括波特率如何计算)

目录 串口通信实验通信的基本概念串行通信与并行通信异步通信与同步通信单工、 半双工与全双工通信通信速率 51单片机串口介绍串口介绍串口通信简介串口相关寄存器串口工作方式方式0方式1方式 2 和方式 3 串口的使用方法&#xff08;计算波特率&#xff09; 硬件设计软件设计1、…

C语言第二十二弹---指针(六)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1. 回调函数是什么&#xff1f; 2、qsort使用举例 2.1、使用qsort函数排序整型数据 2.2 使用qsort排序结构体数据 3、qsort函数的模拟实现 总结 1. 回…

机器学习---概率图模型(概率计算问题)

1. 直接计算法 给定模型和观测序列&#xff0c;计算观测序列O出现的概率。最直接 的方法是按概率公式直接计算.通过列举所有可能的长度为T的状态序列&#xff0c;求各个状 态序列 I 与观测序列的联合概率&#xff0c;然后对所有可能的状态序列求和&#xff0c;得 到。 状态…

【C++】多态语法概念

目录 一、概念及定义二、虚函数重写的特例三、final和override四、抽象类 一、概念及定义 概念&#xff1a;在继承关系下的不同类&#xff0c;调用同一个函数&#xff0c;产生不同的行为&#xff0c;叫作多态。 图示&#xff1a; 定义&#xff1a;必须通过基类的指针或者引…

代码随想录算法训练营第四十八天(动态规划篇之01背包)| 1049. 最后一块石头的重量Ⅱ,494. 目标和

1049. 最后一块石头的重量Ⅱ 题目链接&#xff1a;1049. 最后一块石头的重量 II - 力扣&#xff08;LeetCode&#xff09; 思路 尽量将石头分为重量相同的两堆&#xff0c;这样两堆中的石头相撞之后剩下的石头就会最小。根据之前的01背包理论&#xff1a; 代码随想录算法训…

C语言easyx 贪吃蛇大作战,没有模仿,只有超越

作品名称:贪吃蛇大作战 版本历史和日期:V1.0 - 2024年2月11日 简介: 贪吃蛇大作战是一个基于EasyX图形库的经典贪吃蛇游戏。玩家通过键盘控制贪吃蛇的移动方向,目标是吃掉屏幕上随机生成的食物点,每吃掉一个食物点,蛇身就会增长一节。游戏提供三种模式:无屏障模式、有…

2024牛客寒假算法基础集训营2

C Tokitsukaze and Min-Max XOR 题目大意 给定一个数组从任取数构成序列序列满足&#xff0c;&#xff08;可以只取一个数&#xff09;问能构造出多少个 解题思路 定找双枚举时间复杂度到&#xff0c;考虑利用加速统计的方案&#xff0c;即将数字按二进制位拆分挂在树上对于…

vtk三维场景基本要素 灯光、相机、颜色、纹理映射 简介

整理一下VTK 三维场景基本要素&#xff0c;后面会一一进行整理&#xff1b; 1. 灯光 vtkLight 剧场里有各式各样的灯光&#xff0c;三维渲染场景中也一样&#xff0c;可以有多个灯光存在。灯光和相机 是三维渲染场景必备的要素&#xff0c;vtkRenderer会自动创建默认的灯光和…

第76讲安全退出实现

安全退出实现 VueX 是一个专门为 Vue.js 应用设计的状态管理构架&#xff0c;统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data )。 Vuex有五个核心概念&#xff1a; state, getters, mutations, actions, modules。 state&#xff1a;vuex的基本数…

Blazor 子组件交互例子

源码 子组件 SwitchBar.razor &#xfeff;using Microsoft.Extensions.Logging inject ILogger<Index> Logger<div style"ClassString" onclick"OnClick">ChildContent </div>code {[Parameter]public RenderFragment? ChildContent…