电子词典dictionary
一、项目要求:
1.登录注册功能,不能重复登录,重复注册。用户信息也存储在数据库中。
2.单词查询功能
3.历史记录功能,存储单词,意思,以及查询时间,存储在数据库
4.基于TCP,支持多客户端连接
5.采用数据库保存用户信息与历史记录
6.将dict.txt的数据导入到数据库中保存。
7.返回上级、按下ctrl+c退出客户端后,该用户退出登录
二、格式要求:
1.main函数只跑逻辑,不允许跑功能代码
2.功能代码封装成函数
三、项目功能:
1.注册
2.登录
3.查询单词
4.查看历史记录
5.退出登录
四、框架设计:
4.1服务器设计
4.2客户端设计
五、功能说明:
5.1用户注册
输入用户名和密码,插入用户表中,用户名不能和已有用户名字冲突,否则失败。
5.2用户登录
输入用户名和密码,通过遍历表中数据,核对数据信息,成功,转到第二个操作界面。
5.3查询单词
输入单词,在词典文件中查找,存在得到单词解释,并且将查询记录保存到记录表中。
5.4查询历史记录
遍历记录表中数据,将用户查询的时间和单词打印到终端上。
5.5多进程实现TCP并发
六、具体代码:
head.h:
#ifndef __HEAD_H__
#define __HEAD_H__#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>#define PORT 8808
#define IP "127.0.0.1"
#define ERR_MSG(msg) { fprintf(stderr,"__%d__",__LINE__); perror(msg); }int put_dict(sqlite3 *db);
void handler(int sig);
int do_register(sqlite3 *db,char *buf);
void do_register_cli(char *buf);
int Register(sqlite3 *db,char *buf);
void do_login(char *buf);
int Login(sqlite3 *db,char *buf);
int do_select_user(sqlite3 *db,char *name);
int do_insert(sqlite3 *db,char *words,char *mean,char *save_buf);
int Search(sqlite3 *db,char *buf,char *save_buf);
int Search_res(sqlite3 *db,char *buf,char *save_buf);
int deal_cli_msg(int newfd,struct sockaddr_in cin,sqlite3 *db);#endif
dictionary.c(功能函数):
#include "head.h"//导入词典
int put_dict(sqlite3 *db)
{//创建并打开一个数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){printf("sqlite3_open:%s %d __%d__\n",\sqlite3_errmsg(db),sqlite3_errcode(db),__LINE__);return -1;}//创建一个表格 create table stu (id int,name char,score float);//数据库中sql语句怎么写,这里就怎么写char sql[128] = "create table dict (word char,mean char);";char* errmsg = NULL;if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_open:%s %d __%d__\n",\errmsg,sqlite3_errcode(db),__LINE__);return -1;}//打开文件FILE* fp = fopen("./dict.txt","r");if(NULL == fp){perror("fopen");return -1;}//循环读取文件中的数据,一行一行的读取char buf[256] = "";char word[32] = "";char mean[200] = "";int count = 1;int i =0;char* ptr = NULL;while(1){if(fgets(buf,sizeof(buf),fp) == NULL)break;buf[strlen(buf)-1] = 0;//分离单词和意思bzero(word,sizeof(word));bzero(mean,sizeof(mean));//获取" "子串在buf中的地址ptr = strstr(buf," ");if(NULL == ptr){printf("没有找到对应子串\n");break;}strncpy(word,buf,ptr-buf); //" "子串前面是单词strcpy(mean,ptr+3); //" "子串后面是意思//插入到数据库中sprintf(sql,"insert into dict values(\"%s\",\"%s\");",word,mean);if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){printf("sqlite3_exec failed:%s __%d__\n",errmsg,__LINE__);return -1;}}printf("数据库建立成功\n");//关闭文件fclose(fp);//关闭数据库if(sqlite3_close(db) != SQLITE_OK){fprintf(stderr,"sqlite3_close:%s %d __%d__\n",\sqlite3_errmsg(db),sqlite3_errcode(db),__LINE__);return -1;}return 0;
}//捕获信号
void handler(int sig)
{while(waitpid(-1, NULL, WNOHANG) > 0);
}//实现注册功能
int do_register(sqlite3 *db,char *buf)
{//打开数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);return -1;}//创建一个表char sql[128] = "create table if not exists user (name char,passwd char);";char *errmsg = NULL;if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}char *name = buf+2;char *passwd = buf+2+strlen(buf+2)+1;if(do_select_user(db,name) == 1){if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 1;}sprintf(sql,"insert into user values ('%s','%s');",name,passwd);if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}printf("register success...\n");//关闭数据库,释放对应的内存空间if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 0;
}//客户端注册函数
void do_register_cli(char *buf)
{char name[32] = "";char passwd[32] = "";printf("请输入您的用户名>>>");scanf("%s",name);getchar();printf("请输入您的密码>>>");scanf("%s",passwd);getchar();sprintf(buf,"%s%c%s%c%s","1",0,name,0,passwd);
}//实现注册功能
int Register(sqlite3 *db,char *buf)
{//打开数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);return -1;}//创建一个表char sql[128] = "create table if not exists user (name char,passwd char);";char *errmsg = NULL;if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}char *name = buf+2;char *passwd = buf+2+strlen(buf+2)+1;if(do_select_user(db,name) == 1){if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 1;}sprintf(sql,"insert into user values ('%s','%s');",name,passwd);if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}printf("register success...\n");//关闭数据库,释放对应的内存空间if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 0;
}//登录函数
void do_login(char *buf)
{char name[32] = "";char passwd[32] = "";printf("请输入用户名>>>");scanf("%s",name);getchar();printf("请输入密码>>>");scanf("%s",passwd);getchar();sprintf(buf,"%s%c%s%c%s","2",0,name,0,passwd);
}//实现登录功能
int Login(sqlite3 *db,char *buf)
{//打开数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);return -1;}char sql[128] = "create table if not exists user (name char,passwd char);";char *errmsg = NULL;if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}strcpy(sql,"select * from user;");char **pres = NULL;int row,column;if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}char *name = buf+2;char *passwd = buf+2+strlen(buf+2)+1;for(int i=2;i<(row+1)*column;i++){if(strcmp(pres[i],name) == 0 && strcmp(pres[i+1],passwd) == 0){printf("login success...\n");if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 2;}}//关闭数据库,释放对应的内存空间if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 3;
}//查找用户名是否存在
int do_select_user(sqlite3 *db,char *name)
{char sql[128] = "select name from user;";char **pres = NULL;int row,column;char *errmsg = NULL;if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}for(int i=1;i<(row+1)*column;i++){if(strcmp(pres[i],name) == 0){fprintf(stderr,"sqlite3_exec: name already existss\n");return 1;}}return 0;
}//实现查询功能函数
int do_insert(sqlite3 *db,char *words,char *mean,char *save_buf)
{//获取当前时间戳time_t t;struct tm *info=NULL;char mytime[128] = "";t = time(NULL);info = localtime(&t);sprintf(mytime,"%d-%02d-%02d %02d:%02d:%02d",info->tm_year+1900,info->tm_mon+1,info->tm_mday,info->tm_hour,info->tm_min,info->tm_sec);//打开数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);return -1;}//创建一个表char sql[128] = "create table if not exists history (name char,word char,mean char,time char);";char *errmsg = NULL;char *name = save_buf;if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}//插入查询记录sprintf(sql,"insert into history values (\"%s\",\"%s\", \"%s\",\"%s\");",name,words, mean,mytime);if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("sqlite3_exec failed:%s __%d__\n", errmsg, __LINE__);return -1;}printf("do_insert success...\n");
}//查询单词
int do_search(sqlite3 *db,char *buf,char *save_buf)
{//打开数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);return -1;}char sql[128] = "select * from dict;";char **pres = NULL;int row,column;char *errmsg = NULL;if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_get_table: %s __%d__\n",errmsg,__LINE__);return -1;}char *words = buf+2;for(int i=0;i<(row+1)*column;i++){if(strcmp(pres[i],words) == 0){//若查询成功,则将该单词插入记录do_insert(db,words,pres[i+1],save_buf);bzero(buf, sizeof(buf));sprintf(buf,"\t%s\t\t%s\t",pres[i],pres[i+1]);if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 4;}}//关闭数据库,释放对应的内存空间if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}return 5;
}//查询记录函数
int do_search_res(sqlite3 *db,char *buf,char *save_buf)
{//打开数据库if(sqlite3_open("./dict.db",&db) != SQLITE_OK){fprintf(stderr,"sqlite3_open: %s __%d__\n",sqlite3_errmsg(db),__LINE__);return -1;}char sql[128] = "create table if not exists history (name char,word char,mean char,time char);";char *errmsg = NULL;if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_exec: %s __%d__\n",errmsg,__LINE__);return -1;}char msg[128] = "";strcpy(sql,"select * from history;");char **pres = NULL;int row,column;if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK){fprintf(stderr,"sqlite3_get_table: %s __%d__\n",errmsg,__LINE__);return -1;}bzero(buf,sizeof(buf));for(int i=4;i<(row+1)*column;i++){if(i%4==0 && strcmp(save_buf,pres[i]) == 0){sprintf(msg,"%s\t%s\t%s\t%s\n",pres[i],pres[i+1],pres[i+2],pres[i+3]);strcat(buf,msg);}}if(strlen(buf)!=0)*(buf+strlen(buf)-1) = 0;//关闭数据库,释放对应的内存空间if(sqlite3_close(db) != SQLITE_OK){printf("sqlite3_close failed:%s __%d__\n", sqlite3_errmsg(db), __LINE__);return -1;}if(strlen(buf) == 0)return 7;return 6;
}
//服务器子进程处理客户端信息
int deal_cli_msg(int newfd,struct sockaddr_in cin,sqlite3 *db)
{int flag = 0;char buf[128] = "";char save_buf[128] = "";ssize_t res = 0;int f_res = -1;while(1){bzero(buf, sizeof(buf));//接收数据res = recv(newfd, buf, sizeof(buf), 0);if(res < 0){ERR_MSG("recv");return -1;}else if(0 == res){printf("[%s : %d] client offline\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));break;}//调用功能函数if(strcmp(buf,"1") == 0)f_res = Register(db,buf); //注册else if(strcmp(buf,"2") == 0){f_res = Login(db,buf); //登录strcpy(save_buf,buf+2); //将用户名另存}else if(strcmp(buf,"3") == 0){f_res = do_search(db,buf,save_buf); //查询单词}else if(strcmp(buf,"4") == 0)f_res = do_search_res(db,buf,save_buf); //查询记录//发送数据if(0 == f_res){bzero(buf, sizeof(buf));strcpy(buf,"[注册成功!]");}else if(1 == f_res){bzero(buf, sizeof(buf));strcpy(buf,"[对不起,注册失败,该用户名已存在!]");}else if(2 == f_res){bzero(buf, sizeof(buf));strcpy(buf,"[登录成功!]");}else if(3 == f_res){bzero(buf, sizeof(buf));strcpy(buf,"[对不起,登录失败,该用户名/密码不存在!]");}else if(5 == f_res){bzero(buf, sizeof(buf));strcpy(buf,"[对不起,无法查找找到该单词!]");}else if(7 == f_res){bzero(buf, sizeof(buf));strcpy(buf,"[对不起,该用户没有历史记录!]");}if(send(newfd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}}close(newfd);return 0;
}
服务器(Ser.c):
#include "head.h"
int main(int argc, const char *argv[])
{sqlite3 *db = NULL;if(signal(17, handler) == SIG_ERR){ERR_MSG("signal");return -1;}//导入词典 put_dict(db);//创建流式套接字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) { perror("setsockopt");return -1;}//绑定服务器IP和端口号struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) < 0){ERR_MSG("bind");return -1;}//将套接字设置为被动监听状态if(listen(sfd,10) < 0){ERR_MSG("listen");return -1;}int newfd = -1;struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);//从已完成连接的队列中获取一个客户端信息,生成一个新的文件描述符while(1){newfd = accept(sfd,(struct sockaddr *)&cin,&addrlen);if(newfd < 0){ERR_MSG("accept");return -1;}printf("[%s : %d] connect success...\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));if(0 == fork()){close(sfd);deal_cli_msg(newfd,cin,db);exit(0);}close(newfd);}close(sfd);return 0;
}
客户端(Cli.c):
#include "head.h"int main(int argc, const char *argv[])
{sqlite3 *db =NULL;//创建流式套接字int cfd = socket(AF_INET, SOCK_STREAM, 0);if(cfd < 0){ERR_MSG("socket");return -1;}printf("cfd = %d\n", cfd);//绑定客户端的的IP和端口--->非必须绑定//若不绑定,则操作系统会给客户端绑定上客户端所在的主机IP,以及随机端口(49152~65535)//填充服务器的地址信息结构体,真实的地址信息结构体根据地址族指定//AF_INET: man 7 ip //要连接哪个服务器,就填对应服务器的IP和端口struct sockaddr_in sin;sin.sin_family = AF_INET; //必须填AF_INETsin.sin_port = htons(PORT); //端口号: 填服务器绑定端口号sin.sin_addr.s_addr = inet_addr(IP); //IP地址:服务器绑定的IP地址//连接服务器if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("connect");return -1;}printf("connect success\n");ssize_t res = 0;char buf[128] = "";char buf1[128] ="";char save_buf[128] ="";char choose = 0;while(1){system("clear");printf("-----------------------\n");printf("---------1.注册--------\n");printf("---------2.登录--------\n");printf("---------3.退出--------\n");printf("-----------------------\n");printf("请输入您需要执行的操作>>>");choose = getchar();while(getchar() != 10);switch(choose){case '1'://注册函数do_register_cli(buf);break;case '2'://登录函数do_login(buf);break;case '3'://退出函数goto END;default:printf("对不起,您的输入有误,请重新输入\n");}//发送数据if(send(cfd,buf,sizeof(buf),0) < 0){perror("send");return -1;}//接受数据bzero(buf,sizeof(buf));res = recv(cfd,buf,sizeof(buf),0);if(res < 0){perror("recv");return -1;}else if(0 == res){printf("[%s : %d] server offline\n",IP,PORT);break;}printf("%s\n",buf);strcpy(save_buf,buf);while(strcmp(save_buf,"[登录成功!]") == 0){system("clear");printf("--------------------------\n");printf("-------1.查找单词---------\n");printf("-------2.查找历史记录-----\n");printf("-------3.退出登录---------\n");printf("--------------------------\n");printf("请输入您要执行的操作>>>");choose = getchar();while(getchar() != 10);// bzero(buf,sizeof(buf));// fgets(buf,sizeof(buf),stdin);// buf[strlen(buf)-1] = 0;char words[20] = "";switch(choose){case '1':{while(1){bzero(buf,sizeof(buf));printf("请输入您要查找的单词(输入 \"#\" 结束)>>>");scanf("%s",words);getchar();if(strcmp(words,"#") == 0)break;sprintf(buf,"%s%c%s%c","3",0,words,0);//发送数据if(send(cfd,buf,sizeof(buf),0) < 0){perror("send");return -1;}//接收查询单词结果bzero(buf,sizeof(buf));res = recv(cfd,buf,sizeof(buf),0);if(res < 0){perror("recv");return -1;}else if(0 == res){printf("[%s : %d] server offline\n",IP,PORT);// break;goto END;}printf("%s\n",buf);}}break;case '2'://登录函数{sprintf(buf,"%s%c","4",0);//发送数据if(send(cfd,buf,sizeof(buf),0) < 0){perror("send");return -1;}//接受查询单词结果bzero(buf,sizeof(buf));res = recv(cfd,buf,sizeof(buf),0);if(res < 0){perror("recv");return -1;}else if(0 == res){printf("[%s : %d] server offline\n",IP,PORT);goto END;// break;}printf("%s\n",buf);}break;case '3':goto END1;default:printf("对不起,您的输入有误,请重新输入\n");}printf("输入任意字符清屏>>>");while(getchar() != 10);}
END1:printf("输入任意字符清屏>>>");while(getchar() != 10);}
END://关闭所有文件描述符close(cfd);return 0;
}
相关文章:

电子词典dictionary
一、项目要求: 1.登录注册功能,不能重复登录,重复注册。用户信息也存储在数据库中。 2.单词查询功能 3.历史记录功能,存储单词,意思,以及查询时间,存储在数据库 4.基于TCP,支持多客户…...

【python爬虫】10.指挥浏览器自动工作(selenium)
文章目录 前言selenium是什么怎么用设置浏览器引擎获取数据解析与提取数据自动操作浏览器 实操运用确认目标分析过程代码实现 本关总结 前言 上一关,我们认识了cookies和session。 分别学习了它们的用法,以及区别。 还做了一个项目:带着小…...

QT文件对话框,将标签内容保存至指定文件
一、主要步骤 首先,通过getSaveFileName过去想要保存的文件路径及文件名,其次,通过QFile类实例化一个文件对象,再读取文本框中的内容,最后将读取到的内容写入到文件中,最后关闭文件。 1.txt即为完成上述操作…...

C#,《小白学程序》第十一课:阶乘(Factorial)的计算方法与代码
1 文本格式 /// <summary> /// 阶乘的非递归算法 /// </summary> /// <param name"a"></param> /// <returns></returns> private int Factorial_Original(int a) { int r 1; for (int i a; i > 1; i--) { …...

MySQL 数据库常用命令大全(完整版)
文章目录 1. MySQL命令2. MySQL基础命令3. MySQL命令简介4. MySQL常用命令4.1 MySQL准备篇4.1.1 启动和停止MySQL服务4.1.2 修改MySQL账户密码4.1.3 MySQL的登陆和退出4.1.4 查看MySQL版本 4.2 DDL篇(数据定义)4.2.1 查询数据库4.2.2 创建数据库4.2.3 使…...
【数学】【书籍阅读笔记】【概率论】应用随机过程概率论模型导论 by Sheldon M.Ross 第一章 概率论引总结与习题题解 【更新中】
文章目录 前言1 第一章 概率论引论 总结1.1 样本空间与事件1.2 定义在事件上的概率1.3 条件概率1.4 独立事件 2 一些有用的重要结论/公式/例题3 重要例题例 1.11 3 习题题解题1题2 4 习题总结 前言 1 第一章 概率论引论 总结 第一章从事件的角度引出样本空间、事件、概率的基本…...

posexplode函数实战总结
目录 1、建表和准备数据 2、炸裂实践 3、错误炸裂方式 4、当字段类型为string,需要split一下 对单列array类型的字段进行炸裂时,可以使用lateral view explode。 对多列array类型的字段进行炸裂时,可以使用lateral view posexplode。 1…...

QTday3(对话框、发布软件、事件处理核心机制)
一、Xmind整理: 二、上课笔记整理: 1.消息对话框(QMessageBox) ①基于属性版本的API QMessageBox::QMessageBox( //有参构造函数名QMessageBox::Icon icon, //图标const Q…...

el-date-picker限制选择的时间范围
<el-date-pickersize"mini"v-model"dateTime"value-format"yyyy-MM-dd HH:mm:ss"type"datetimerange"range-separator"~"start-placeholder"开始日期"end-placeholder"结束日期":picker-options&quo…...
Scala中的Actor模型
Scala中的Actor模型 概念 Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼。Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,…...

Java使用pdfbox将pdf转图片
前言 目前比较主流的两种转pdf的方式,就是pdfbox和icepdf,两种我都尝试了下,icepdf解析出来有时候会出现中文显示不出来,网上的解决方式又特别麻烦,不是安装字体,就是重写底层类,所以我选择了p…...
大规模场景下对Istio的性能优化
简介 当前istio下发xDS使用的是全量下发策略,也就是网格里的所有sidecar(envoy),内存里都会有整个网格内所有的服务发现数据。这样的结果是,每个sidecar内存都会随着网格规模增长而增长。 Aeraki-mesh aeraki-mesh项目下有一个子项目专门用来…...

数字化新零售平台系统提供商,门店商品信息智慧管理-亿发进销存
传统的批发零售业务模式正面临着市场需求变化的冲击。用户日益注重个性化、便捷性和体验感,新兴的新零售模式迅速崛起,改变了传统的零售格局。如何在保持传统业务的基础上,变革发展,成为了业界亟需解决的问题。 在这一背景下&…...

postgresql-窗口函数
postgresql-窗口函数 简介窗口函数的定义分区选项(PARTITION BY)排序选项(ORDER BY)窗口选项(frame_clause) 聚合窗口函数排名窗口函数演示了 CUME_DIST 和 NTILE 函数 取值窗口函数 简介 常见的聚合函数&…...

Revit SDK 介绍:CreateAirHandler 创建户式风管机
前言 这个例子介绍如何通过 API 创建一个户式风管机族的内容,包含几何和接头。 内容 效果 核心逻辑 必须打开机械设备的族模板创建几何实体来表示风管机创建风机的接头 创建几何实体来表示风管机 例子中创建了多个拉伸,下面仅截取一段代码ÿ…...
微信小程序云开发-云函数发起https请求简易封装函数
一、前言 在日常的开发中,经常会遇到需要请求第三方API的情况,例如请求实名认证接口、IP转换地址接口等等。这些请求放在小程序前端的话,就需要把密钥放在客户端,在安全性上没这么高。 因此,一般是放在云函数端去访问…...
深入探索PHP编程:连接数据库的完整指南
深入探索PHP编程:连接数据库的完整指南 在现代Web开发中,与数据库进行交互是不可或缺的一部分。PHP作为一种强大的服务器端编程语言,提供了丰富的工具来连接和操作各种数据库系统。本篇教程将带您了解如何在PHP中连接数据库,执行…...

【Centos8配置节点免密登陆】
登录Centos8 配置免密登录 为什么需要配置免密登录,玩大数据,玩集群的朋友们,都需要使用RPC通讯,完成集群命令同步,数据操作通讯。要实现RPC通讯,就需要配置节点之间的免密登录。 # 配置登录秘钥 ssh-key…...

不可变集合、Lambda表达式、Stream流
不可变集合、Lambda表达式、Stream流 创建不可变集合 不能被修改的集合 应用场景 如果某个数据不能被修改,把它防御性的拷贝到不可变集合中是个很好的实践。 当集合对象被不可信的库调用时,不可变形式是安全的。 创建不可变集合 在List、Set、Map接口中…...
Three.js GLTF模型加载
在Three.js中,要加载三维模型文件,可以使用GLTF格式。GLTF是一种基于JSON的开放标准,用于3D模型的交换和运行时加载。本篇文章将详细讲解如何使用Three.js加载GLTF模型。 ## 1. 下载GLTF模型 在开始之前,请确保您已经有一个GLTF模…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...