当前位置: 首页 > news >正文

Linux网络编程:libevent事件通知库

文章目录:

一:libevent库

二:libevent框架

1.常规事件event

1.1 创建事件event(event_new) 

1.2 添加事件到 event_base(event_add) 

1.3 从event_base上摘下事件(event_del)

1.4 销毁事件(event_free)

1.5 未决和非未决

read_fifo.c

write_fifo.c

2.带缓冲区的事件bufferevent

2.1 带缓冲区的事件 bufferevent

2.2 创建、销毁bufferevent(bufferevent_socket_new 、bufferevent_socket_free)

2.3 给bufferevent设置回调(bufferevent_setcb)

2.4 启动、关闭 bufferevent的 缓冲区(bufferevent_enable、bufferevnet_disable)

三:网络通信 

1.服务端

1.1 创建和释放监听服务器(evconnlistener_new_bind、evconnlistener_free) 

1.2 服务器端 libevent 创建TCP连接流程

ev_server.c

2.客户端

2.1 连接客户端(bufferevent_socket_connect) 

2.2 Libevent实现TCP客户端流程 

ev_client.c


一:libevent库

libevent官网

libevent库开源;精简;跨平台(Windows、Linux、maxos、unix);专注于网络通信源码包安装:  参考 README、readme./configure		    检查安装环境 生成 makefilemake			    生成 .o 和 可执行文件sudo make install	将必要的资源cp置系统指定目录进入 sample 目录,运行demo验证库安装使用情况编译使用库的 .c 时,需要加 -levent 选项库名 libevent.so --> /usr/local/lib   查看的到特性:基于“事件”异步通信模型。--- 回调

二:libevent框架

libevent框架:1. 创建 event_base		(乐高底座)struct event_base *event_base_new(void);struct event_base *base = event_base_new();2. 创建 事件evnet	   (积木)常规事件       event	   --> event_new(); 带缓冲区的事件 bufferevent --> bufferevent_socket_new();3. 将事件 添加到 base上	int event_add(struct event *ev, const struct timeval *tv)4. 循环监听事件满足int event_base_dispatch(struct event_base *base);event_base_dispatch(base);5. 释放 event_baseevent_base_free(base);

1.常规事件event

1.1 创建事件event(event_new) 

创建事件event:struct event *ev;struct event *event_new(struct event_base *base,evutil_socket_t fd,short what,event_callback_fn cb;  void *arg);base: event_base_new()返回值fd: 绑定到 event 上的 文件描述符what:对应的事件(r、w、e)EV_READ		一次 读事件EV_WRTIE	一次 写事件EV_PERSIST	持续触发。 结合 event_base_dispatch 函数使用,生效cb:一旦事件满足监听条件,回调的函数typedef void (*event_callback_fn)(evutil_socket_t fd,  short,  void *)	arg: 回调的函数的参数返回值:成功创建的 event

1.2 添加事件到 event_base(event_add) 

添加事件到 event_baseint event_add(struct event *ev, const struct timeval *tv);ev: event_new() 的返回值tv:NULL

1.3 从event_base上摘下事件(event_del)

从event_base上摘下事件				【了解】int event_del(struct event *ev);ev: event_new() 的返回值

1.4 销毁事件(event_free)


销毁事件int event_free(struct event *ev);ev: event_new() 的返回值

1.5 未决和非未决

未决和非未决:非未决: 没有资格被处理未  决:有资格被处理,但尚未被处理event_new --> event ---> 非未决 --> event_add --> 未决 --> dispatch() && 监听事件被触发 --> 激活态 --> 执行回调函数 --> 处理态 --> 非未决 event_add && EV_PERSIST --> 未决 --> event_del --> 非未决

read_fifo.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <event2/event.h>// 对操作处理函数
void read_cb(evutil_socket_t fd, short what, void *arg)
{// 读管道char buf[1024] = {0};int len = read(fd, buf, sizeof(buf));printf("read event: %s \n", what & EV_READ ? "Yes" : "No");printf("data len = %d, buf = %s\n", len, buf);sleep(1);
}// 读管道
int main(int argc, const char* argv[])
{unlink("myfifo");//创建有名管道mkfifo("myfifo", 0664);// open file//int fd = open("myfifo", O_RDONLY | O_NONBLOCK);int fd = open("myfifo", O_RDONLY);if(fd == -1){perror("open error");exit(1);}// 创建个event_basestruct event_base* base = NULL;base = event_base_new();// 创建事件struct event* ev = NULL;ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL);// 添加事件event_add(ev, NULL);// 事件循环event_base_dispatch(base);  // while(1) { epoll();}// 释放资源event_free(ev);event_base_free(base);close(fd);return 0;
}

write_fifo.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <event2/event.h>// 对操作处理函数
void write_cb(evutil_socket_t fd, short what, void *arg)
{// write管道char buf[1024] = {0};static int num = 0;sprintf(buf, "hello,world-%d\n", num++);write(fd, buf, strlen(buf)+1);sleep(1);
}// 写管道
int main(int argc, const char* argv[])
{// open file//int fd = open("myfifo", O_WRONLY | O_NONBLOCK);int fd = open("myfifo", O_WRONLY);if(fd == -1){perror("open error");exit(1);}// 写管道struct event_base* base = NULL;base = event_base_new();// 创建事件struct event* ev = NULL;// 检测的写缓冲区是否有空间写//ev = event_new(base, fd, EV_WRITE , write_cb, NULL);ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);// 添加事件event_add(ev, NULL);// 事件循环event_base_dispatch(base);// 释放资源event_free(ev);event_base_free(base);close(fd);return 0;
}

2.带缓冲区的事件bufferevent

2.1 带缓冲区的事件 bufferevent

带缓冲区的事件 bufferevent#include <event2/bufferevent.h> read/write 两个缓冲. 借助 队列原理: bufferent利用队列实现两个缓冲区(数据读走就没, FIFO);读: 有数据, 读回调函数被调用, 使用bufferevent_read()读数据;写: 使用bufferevent_write, 向写缓冲中写数据, 该缓冲区中有数据自动写出, 写完后, 回调函数被调用(鸡肋);

2.2 创建、销毁bufferevent(bufferevent_socket_new 、bufferevent_socket_free)

创建bufferevent:struct bufferevent* bufferevent_socket_new(struct event_base* base,evutil_socket_t fd,enum bfferevent_options options)base: 基事件, event_base_new函数的返回值;fd:封装到bufferevent内的fd(绑定在一起);enum表示枚举类型, 一般取BEV_OPT_CLOSE_ON_FREE;成功返回bufferevent事件对象;销毁bufferevent:void bufferevent_socket_free(struct bufferevent* ev)

2.3 给bufferevent设置回调(bufferevent_setcb)

给bufferevent设置回调:对比event:	event_new( fd, callback );  					event_add() -- 挂到 event_base 上。bufferevent_socket_new(fd)					bufferevent_setcb( callback )void bufferevent_setcb(struct bufferevent * bufev,bufferevent_data_cb readcb,bufferevent_data_cb writecb,bufferevent_event_cb eventcb,void *cbarg );bufev: bufferevent_socket_new() 返回值readcb: 设置 bufferevent 读缓冲,对应回调  read_cb{  bufferevent_read() 读数据  }writecb: 设置 bufferevent 写缓冲,对应回调 write_cb {  } -- 给调用者,发送写成功通知。  可以 NULLeventcb: 可传NULL;cbarg: 回调函数的参数;eventcb: 设置 事件回调。   也可传NULLtypedef void (*bufferevent_event_cb)(struct bufferevent *bev,  short events, void *ctx);void event_cb(struct bufferevent *bev,  short events, void *ctx){。。。。。}events: BEV_EVENT_CONNECTEDread 读回调函数类型(read_cb :bufferevent_read()):typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void*ctx);void read_cb(struct bufferevent *bev, void *cbarg ){.....bufferevent_read();   --- read();}bufferevent_read()函数的原型:size_t bufferevent_read(struct bufferevent *bev, void *buf, size_t bufsize);write 写回调函数类型(bufferevent_write):int bufferevent_write(struct bufferevent *bufev, const void *data,  size_t size); 

2.4 启动、关闭 bufferevent的 缓冲区(bufferevent_enable、bufferevnet_disable)

启动、关闭 bufferevent的 缓冲区:void bufferevent_enable(struct bufferevent* bufev,short events);		//启用缓冲区void bufferevnet_disable(struct bufferevent* bufev,short events);		//禁用	events的值可传入三个宏: EV_READ、EV_WRITE、EV_READ|EV_WRITE默认、write 缓冲是 enable、read 缓冲是 disablebufferevent_enable(evev, EV_READ);		-- 开启读缓冲

三:网络通信 

1.服务端

1.1 创建和释放监听服务器(evconnlistener_new_bind、evconnlistener_free) 

创建监听服务器:------ socket();bind();listen();accept();struct evconnlistener * listner//这一个函数可以完成`socket(),bind(),listen(),accept()`四个函数的作用struct evconnlistener *evconnlistener_new_bind (	struct event_base *base,evconnlistener_cb cb, void *ptr, unsigned flags,int backlog,const struct sockaddr *sa,int socklen);base: event_basecb: 回调函数。 一旦被回调,说明在其内部应该与客户端完成, 数据读写操作,进行通信ptr: 回调函数的参数flags: LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLEbacklog: listen() 2参。 -1 表最大值sa:服务器自己的地址结构体socklen:服务器自己的地址结构体大小返回值:成功创建的监听器//回调函数的类型typedef void (*evconnlistener_cb)(struct evconnlistener* listener,evutil_socker_t sock,struct sockaddr* addr,int len,void* ptr);listener:evconnlistener_new_bind函数的返回值;sock:用于通信的文件描述符;addr:客户端的地址结构;len:客户端地址结构的长度;ptr:外部ptr传进来的值;释放监听服务器:void evconnlistener_free(struct evconnlistener *lev);

1.2 服务器端 libevent 创建TCP连接流程

服务器端 libevent 创建TCP连接:1. 创建event_base2. 创建bufferevent事件对象。bufferevent_socket_new()3. 使用bufferevent_setcb() 函数给 bufferevent的 read、write、event 设置回调函数4. 当监听的 事件满足时,read_cb会被调用, 在其内部 bufferevent_read()读5. 使用 evconnlistener_new_bind 创建监听服务器, 设置其回调函数,当有客户端成功连接时,这个回调函数会被调用6. 封装 listner_cb() 在函数内部。完成与客户端通信7. 设置读缓冲、写缓冲的 使能状态 enable、disable8. 启动循环 event_base_dispath()9. 释放连接

ev_server.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>// 读缓冲区回调
void read_cb(struct bufferevent *bev, void *arg)
{char buf[1024] = {0}; // 借助读缓冲,从客户端拿数据  bufferevent_read(bev, buf, sizeof(buf));printf("client say: %s\n", buf);char *p = "我是服务器, 已经成功收到你发送的数据!";// 借助写缓冲,写数据回给客户端bufferevent_write(bev, p, strlen(p)+1);sleep(1);
}// 写缓冲区回调
void write_cb(struct bufferevent *bev, void *arg)
{printf("I'm服务器, 成功写数据给客户端,写缓冲区回调函数被回调...\n"); 
}// 事件
void event_cb(struct bufferevent *bev, short events, void *arg)
{if (events & BEV_EVENT_EOF){printf("connection closed\n");  }else if(events & BEV_EVENT_ERROR)   {printf("some other error\n");}bufferevent_free(bev);    printf("buffevent 资源已经被释放...\n"); 
}// 被回调,说明有客户端成功连接, cfd已经传入该参数内部。 创建bufferevent事件对象
//与客户端完成读写操作
void cb_listener(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int len, void *ptr)
{printf("connect new client\n");struct event_base* base = (struct event_base*)ptr;// 通信操作// 创建添加新事件bufferevent 对象struct bufferevent *bev;bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);// 给bufferevent缓冲区设置回调 read、write、eventvoid bufferevent_setcb(struct bufferevent * bufev,bufferevent_data_cb readcb,bufferevent_data_cb writecb,bufferevent_event_cb eventcb,void *cbarg );//设置回调函数bufferevent_setcb(bev, read_cb, write_cb, event_cb,NULL,NULL);//启动 read 缓冲区的 使能状态bufferevent_enable(bev, EV_READ);
}int main(int argc, const char* argv[])
{// 定义服务器地址结构init server struct sockaddr_in serv;memset(&serv, 0, sizeof(serv));serv.sin_family = AF_INET;serv.sin_port = htons(9876);serv.sin_addr.s_addr = htonl(INADDR_ANY);// 创建event_basestruct event_base* base;base = event_base_new();// 创建套接字// 绑定// 创建服务器监听器:接收连接请求struct evconnlistener* listener;                                            //监听器listener = evconnlistener_new_bind(base, cb_listener, base, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 36, (struct sockaddr*)&serv, sizeof(serv));//启动监听循环event_base_dispatch(base);//销毁event_baseevconnlistener_free(listener);event_base_free(base);return 0;
}

2.客户端

2.1 连接客户端(bufferevent_socket_connect) 

连接客户端:socket();connect();int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);bev: bufferevent 事件对象(封装了fd)address、len:等同于 connect() 参2/3

2.2 Libevent实现TCP客户端流程 

Libevent实现TCP客户端流程1.创建event_basev2.使用bufferevnet_socket_new()创建一个用跟服务器通信的 bufferevnet事件对象3.使用bufferevnet_socket_connect()连接服务器4.使用bufferevent_setcb()给 bufferevnet对象的 read、write、event设置回调5.设置bufferevnet 对象的读写缓冲区enable / disable6.接受、发送数据bufferevent_read() / bufferevent_write()7.启动循环监听event_base_dispatch8.释放资源

ev_client.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/bufferevent.h>
#include <event2/event.h>
#include <arpa/inet.h>void read_cb(struct bufferevent *bev, void *arg)
{char buf[1024] = {0}; bufferevent_read(bev, buf, sizeof(buf));printf("fwq say:%s\n", buf);bufferevent_write(bev, buf, strlen(buf)+1);sleep(1);
}void write_cb(struct bufferevent *bev, void *arg)
{printf("----------我是客户端的写回调函数,没卵用\n"); 
}void event_cb(struct bufferevent *bev, short events, void *arg)
{if (events & BEV_EVENT_EOF){printf("connection closed\n");  }else if(events & BEV_EVENT_ERROR)   {printf("some other error\n");}else if(events & BEV_EVENT_CONNECTED){printf("已经连接服务器...\\(^o^)/...\n");return;}// 释放资源bufferevent_free(bev);
}// 客户端与用户交互,从终端读取数据写给服务器
void read_terminal(evutil_socket_t fd, short what, void *arg)
{// 读数据char buf[1024] = {0};int len = read(fd, buf, sizeof(buf));struct bufferevent* bev = (struct bufferevent*)arg;// 发送数据bufferevent_write(bev, buf, len+1);
}int main(int argc, const char* argv[])
{struct event_base* base = NULL;base = event_base_new();int fd = socket(AF_INET, SOCK_STREAM, 0);// 通信的fd放到bufferevent中struct bufferevent* bev = NULL;bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);// init server infostruct sockaddr_in serv;memset(&serv, 0, sizeof(serv));serv.sin_family = AF_INET;serv.sin_port = htons(9876);inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);// 连接服务器bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));// 设置回调bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);// 设置读回调生效// bufferevent_enable(bev, EV_READ);// 创建事件struct event* ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST,read_terminal, bev);// 添加事件                     event_add(ev, NULL);event_base_dispatch(base);event_free(ev);event_base_free(base);return 0;
}

相关文章:

Linux网络编程:libevent事件通知库

文章目录&#xff1a; 一&#xff1a;libevent库 二&#xff1a;libevent框架 1.常规事件event 1.1 创建事件event&#xff08;event_new&#xff09; 1.2 添加事件到 event_base&#xff08;event_add&#xff09; 1.3 从event_base上摘下事件&#xff08;event_del&a…...

java.lang.reflect.InvocationTargetException:null报未知异常

在项目上线过程中&#xff0c;突然出现大量异常信息&#xff0c;堆栈信息如下&#xff1a; java.lang.reflect.InvocationTargetException: null at jdk .internal.reflect.GeneratedMethodAccessor792 .invoke(Unknown Source) ~[?:?] at jdk.internal.reflect.DelegatingM…...

MySQL高级篇——MySQL架构篇1(Linux下MySQL8的安装与使用)

目录 0 安装前0.1 Linux系统及工具的准备0.2 查看是否安装过MySQL0.3 MySQL的卸载 1 MySQL8的Linux版安装1.1 MySQL的4大版本1.2 下载MySQL指定版本1.3 CentOS7下检查MySQL依赖1.4 CentOS7下MySQL安装过程 2 MySQL登录2.1 首次登录2.2 修改密码2.3 设置远程登录 3 MySQL 8 的密…...

解决 go mod tidy 加载模块超时

如果go mod tidy 加载模块超时 解决方法 修改GOPROXY: 查看go环境相关信息&#xff1a; go envgo env -w GOPROXYhttps://goproxy.cn...

金融市场中的机器学习;快手推出自研语言模型“快意”

&#x1f989; AI新闻 &#x1f680; OpenAI可能面临《纽约时报》的起诉&#xff0c;侵犯知识产权引发争议 摘要&#xff1a;OpenAI使用《纽约时报》的文章和图片来训练AI模型&#xff0c;违反了《纽约时报》的服务条款&#xff0c;可能面临巨大损失。此前&#xff0c;也有其…...

【面试刷题】——什么是深拷贝和浅拷贝?

深拷贝&#xff08;Deep Copy&#xff09;和浅拷贝&#xff08;Shallow Copy&#xff09;是在编程中用来描述对象拷贝的两个概念&#xff0c;特别是在涉及对象包含其他对象&#xff08;如嵌套数据结构、指针等&#xff09;的情况下。 浅拷贝&#xff08;Shallow Copy&#xff…...

物联网(IoT)安全挑战与解决方案: 分析物联网设备面临的安全威胁,以及如何设计和管理安全的IoT生态系统

第一章&#xff1a;引言 随着科技的飞速发展&#xff0c;物联网&#xff08;IoT&#xff09;作为连接世界的桥梁&#xff0c;已经成为现代社会不可或缺的一部分。然而&#xff0c;随着IoT设备数量的不断增加&#xff0c;其安全问题也日益显著。本文将深入探讨IoT领域面临的安全…...

Ubuntu 22.04.3 LTS 维护更新发布

近日消息&#xff0c;Canonical 今天发布了代号为 Jammy Jellyfish、长期支持的 Ubuntu 22.04 第 3 个维护版本更新&#xff0c;距离上个版本相隔 6 周时间。 Ubuntu 22.04.3 LTS 最大的亮点在于内核升级到 Linux Kernel 6.2&#xff0c;此外 Mesa 图形堆栈也升级到 23.0.4 版…...

平安健康,找到了医疗服务的价值密码

健康是人类的永恒需求&#xff0c;围绕医疗和健康服务衍生的产业&#xff0c;却苦于无法和用户建立足够紧密、长期的联系。由此&#xff0c;也不得不面临价值从何而来的问题。 作为医疗服务领域的代表性企业&#xff0c;平安健康医疗科技有限公司&#xff08;股票简称“平安好…...

❤ vue 使用原生组件

❤ vue 使用原生组件 1、做一个input输入框验证开始 ① 想让我们的input输入框类型为时间&#xff0c;只需要为我们的输入框简单的加一个类型的type即可 <input type"date" id"birthday" name"birthday" placeholder"年/月/日"&…...

4.12 TCP 连接,一端断电和进程崩溃有什么区别?

目录 TCP keepalive TCP 的保活机制 主机崩溃 进程崩溃 有数据传输的场景 客户端主机宕机&#xff0c;又迅速重启 客户端主机宕机&#xff0c;一直没有重启 TCP连接服务器宕机和进程退出情况总结 TCP keepalive TCP 的保活机制 TCP 保活机制需要通过 socket 接口设置 S…...

十二、pikachu之URL重定向

文章目录 1、URL重定向概述2、实战3、URL跳转的几种方式:3.1 META标签内跳转3.2 javascript跳转3.3 header头跳转 1、URL重定向概述 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。如果后端采用了前端传进来的&#xff08;可能是用户传参&#xff0c;或者之前预埋…...

贝叶斯公式中的动词 命名技巧

一项血液化验有95%的把我诊断某种疾病&#xff0c;但是&#xff0c;这项化验用于健康人也会有1%的“伪阳性”结果(即如果一个健康人接受这项化验&#xff0c;则化验结果乌镇此人患有该疾病的概率是0.01)。如果该疾病的患者事实上只占总人口的0.5%&#xff0c;若某人化验结果为阳…...

ctfshow-web13 文件上传

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 首先看到是一个上传页面&#xff0c;测试其他无果&#xff0c;遂进行目录遍历&#xff0c;发现upload.php.bak文件 可以看到这里的限制条件&#xff0c;大小&#xff0c;以及内容&#xff0c;这里可以使用.use…...

Python项目开发案例————学生信息管理系统(附源码)

一、学生信息管理系统 本文使用Python语言开发了一个学生信息管理系统&#xff0c;该系统可以帮助教师快速录入学生的信息&#xff0c;并且对学生的信息进行基本的增、删、改、查操作&#xff1b;还可以实时地将学生的信息保存到磁盘文件中。 1.1 需求分析 为了顺应互联网时代…...

2023-08-25力扣每日一题

链接&#xff1a; 1448. 统计二叉树中好节点的数目 题意&#xff1a; 判断根节点到每个节点X的过程中&#xff0c;如果没有值大于X&#xff0c;则该节点为好节点&#xff0c;求好节点数量 解&#xff1a; 由于求根节点到其他节点的路径&#xff0c;则使用dfs算法&#xff…...

Vue3中的计算属性和属性监听

compute计算属性 Vue3中可以通过 compute进行监听计算属性&#xff0c;他返回的是一个ref的对象&#xff0c;也就是说 通过compuye这种方式计算属性实际上是进行了ref的操作 import { computed } from vue const user reactive({firstName: A,lastName: B }) // 只有getter的…...

微信开发之一键修改群公告的技术实现

简要描述&#xff1a; 设置群公告 请求URL&#xff1a; http://域名地址/setChatRoomAnnouncement 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必…...

【git】工作场景中常用的git命令

工作场景中常用的git命令 1. 必备改名改邮箱拉代码下来并且创建新分支git commit回滚某个文件删除分支 工作场景中常用的git命令&#xff0c;记录下来方便调取 1. 必备 改名改邮箱 一般与他人合作&#xff0c;至少你提交的名字得被人熟知或者遵循规范&#xff0c;因此需要更改…...

Vue路由(详解)

目录 路由原理 路由到底有什么作用&#xff1f; 路由安装和使用&#xff08;vue2&#xff09; 路由跳转 跳转实例&#xff1a; 路由的传值和取值 传值实例&#xff1a; 查询参和路由参的区别&#xff1a; 嵌套路由 嵌套实例&#xff1a; 路由守卫 守卫实例&#xff1…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...