基于TCP的简易电子词典

头文件:

#ifndef __HEAD_H__
#define __HEAD_H__#include <myhead.h>#define   N  32
typedef struct {int type;char name[N];char data[256];int option;int flag;
}MSG;#define  R  1   // 用户注册
#define  L  2   // 用户登录
#define  Q  3   // 查询单词
#define  H  4   // 历史记录#define  DATABASE  "my.db" //创建的数据库#define SERADDR "192.168.114.156"   
#define SERPORT 8888          #endif

服务器:

#include "head.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;}//创建子进程if((pid = fork()) < 0){perror("fail to fork");return -1;}//子进程else if(pid == 0)  {close(sockfd);do_client(acceptfd, db);}//父进程else  {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("用户已退出\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++;elsebreak;}*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{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);}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, "已到末尾");send(acceptfd, info, sizeof(info), 0);return 1;
}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 "head.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("**********************请输入序号进行对应操作*********************\n");printf("****************************1.注册*******************************\n");printf("****************************2.登录*******************************\n");printf("****************************3.退出*******************************\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("输入不合法,请重新输入\n");}}return 0;
}int SubMenu(int sockfd)
{int n;MSG  msg;while(1){printf("*****************************查询界面****************************\n");printf("**********************请输入序号进行对应操作*********************\n");printf("**************************1.查询单词*****************************\n");printf("**************************2.查询历史记录*************************\n");printf("**************************3.退出*****************************\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("请输入单词 (输入88退出): ");scanf("%s", msg->data);while (getchar() != 10);//如果输入的是#,返回if (strcmp(msg->data, "88") == 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, "已到末尾")){break;}}return 0;}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【若依框架2】前后端分离版本添加功能页

在VSCode的src/views下新建个文件平example,在example下创建test文件夹&#xff0c;在test里创建index.vue文件 <template> <h1>Hello world</h1> </template><script> export default {name: "index" } </script><style s…

2023/9/20总结

maven maven本质是 一个项目管理工具 将项目开发 和 管理过程 抽象成 一个项目对象模型&#xff08;POM&#xff09; POM &#xff08;Project Object Model&#xff09; 项目对象模型 作用 项目构建 提供标准的自动化 项目构建 方式依赖管理 方便快捷的管理项目依赖的资源…

C++【个人笔记1】

1.C的初识 1.1 简单入门 #include<iostream> using namespace std; int main() {cout << "hello world" << endl;return 0; } #include<iostream>; 预编译指令&#xff0c;引入头文件iostream.using namespace std; 使用标准命名空间cout …

springboot整合返回数据统一封装

1、MagCode&#xff0c;错误码枚举类 package com.mgx.common.enums;import lombok.*; import lombok.extern.slf4j.Slf4j;/*** 错误码* author mgx*/ Slf4j NoArgsConstructor AllArgsConstructor public enum MsgCode {/*** 枚举标识&#xff0c;根据业务类型进行添加*/Code…

轻量云服务器租用好在哪

从技术上讲&#xff0c;轻量级云服务器是特化了某一配置的高性价比云服务器的结合。下面&#xff0c;我们将了解轻量级云服务器有什么优 势&#xff0c; 使用物理服务器搭建网站&#xff0c;您需要租用整个服务器&#xff0c;这成本会变得非常昂贵。这对于一些比较简单的使用需…

PostgreSQL 数据库实现公网远程连接

文章目录 前言1. 安装postgreSQL2. 本地连接postgreSQL3. Windows 安装 cpolar4. 配置postgreSQL公网地址5. 公网postgreSQL访问6. 固定连接公网地址7. postgreSQL固定地址连接测试 前言 PostgreSQL是一个功能非常强大的关系型数据库管理系统&#xff08;RDBMS&#xff09;,下…

建议收藏《Verilog代码规范笔记_华为》(附下载)

华为verilog编程规范是坊间流传出来华为内部的资料&#xff0c;其贴合实际工作需要&#xff0c;是非常宝贵的资料&#xff0c;希望大家善存。至于其介绍&#xff0c;在此不再赘述&#xff0c;大家可看下图详细了解&#xff0c;感兴趣的可私信领取《Verilog代码规范笔记_华为》。…

JS【filter过滤器】的用法

在JavaScript中&#xff0c;filter()是一个高阶函数&#xff0c;它是数组(Array)的一部分&#xff0c;可用于创建一个新数组&#xff0c;其中包含通过所提供函数实现的测试的所有元素。 filter()函数的语法如下&#xff1a; let newArray arr.filter(callback(element[, ind…

Spring面试题1:Spring框架的核心功能是什么?Spring框架的好处是什么?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 Spring框架的核心功能是什么 Spring框架的核心功能包括: 控制反转(IoC):Spring通过IoC容器管理对象的生命周期和依赖关系。它将对象的创建、组装和管理…

React中的dispatch()

在React中&#xff0c;dispatch函数是Redux提供的一个方法&#xff0c;用于触发store中的action。它是Redux中的一个核心概念&#xff0c;用于将action传递给store&#xff0c;从而触发相应的状态更新。 当我们调用dispatch函数时&#xff0c;它会将action对象作为参数&#x…

IDEA开发工具技巧

1.1 IDEA相关插件 idea插件下载地址&#xff1a;https://plugins.jetbrains.com/ 开发必装插件&#xff1a; &#xff08;1&#xff09; 快速查找api接口 RestfulTool 插件&#xff0c;推荐指数⭐⭐⭐⭐⭐ [RestfulTool搜索插件使用详解](https://blog.csdn.net/weixin_450147…

Spring学习笔记2 Spring的入门程序

Spring学习笔记1 启示录_biubiubiu0706的博客-CSDN博客 Spring官网地址:https://spring.io 进入github往下拉 用maven引入spring-context依赖 写spring的第一个程序 引入下面依赖,好比引入Spring的基本依赖 <dependency><groupId>org.springframework</groupId&…

【力扣】9. 回文数

题目描述 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;121 是回文&am…

医学影像信息(PACS)系统软件源码

PACS系统是PictureArchivingandCommunicationSystems的缩写&#xff0c;与临床信息系统&#xff08;ClinicalInformationSystem,CIS&#xff09;、放射学信息系统(RadiologyInformationSystem,RIS)、医院信息系统(HospitalInformationSystem,HIS)、实验室信息系统&#xff08;L…

CentOS 7 安装Libevent

CentOS 7 安装Libevent 1.下载安装包 新版本是libevent-2.1.12-stable.tar.gz。&#xff08;如果你的系统已经安装了libevent&#xff0c;可以不用安装&#xff09; 官网&#xff1a;http://www.monkey.org/~provos/libevent/ 2.创建目录 # mkdir libevent-stable 3.解压 …

QT之QString的用法介绍

QT之QString的用法介绍 成员函数常见用法 成员函数 1&#xff09;QString &append(const QString &str) 将 str 字符串追加到当前字符串末尾&#xff0c;并返回修改后的 QString 对象的引用。 2&#xff09;QString &prepend(const QString &str) 将 str 字符…

死锁问题及分析

最近写了一个hiredis的连接池&#xff0c;借鉴了HiRedis库封装&#xff0c;加了些日志&#xff0c;发现这个在ReleaseClient函数中构造shared_ptr时&#xff0c;没有指定delete。修改后在项目使用过程中发现执行一段时间后总是是卡死&#xff0c;使用的是boost库中的锁及其条件…

MES管理系统在生产中的应用及智能工厂的构建思路

在当今制造业中&#xff0c;随着信息化技术和智能化的不断发展&#xff0c;MES生产管理系统已成为工厂生产的核心组成部分。MES管理系统不仅能够提高生产效率&#xff0c;还可以优化生产流程&#xff0c;提升产品质量。本文将详细介绍MES管理系统在工厂生产中的应用以及构建智能…

VCS flow学习

VCS VCS 是IC从业者常用软件&#xff0c;该篇文章是一个学习记录&#xff0c;会记录在使用过程中各种概念及options。 VCS Flow VCS Flow 可以分为Two-step Flow和Three-step Flow两类。 两步法 两步法只支持Verilog HDL和SystemVerilog的design&#xff0c;两步法主要包括…

Windows AD 组策略 关闭自动更新

1、创建组策略 2、配置 计算机配置 → 策略 → 管理模板 → Windows 组件 → Windows 更新 &#xff08;1&#xff09;禁止 配置自动更新 &#xff08;2&#xff09;启用 "删除使用所有Windows更新功能的访问权限" 3、客户机 更新组策略