alin的学习之路(Linux网络编程:八)(libevent库)
alin的学习之路(Linux网络编程:八)(libevent库)
1. libevent库
1. 优点
- 开源
- 精简
- 跨平台
- 专注于网络通信 ——可以借助fd来进行 pipe、fifo 等通信
2. 下载安装
-
下载地址:https://libevent.org/
-
解压缩:tar zxvf libevent-2.1.8-stable.tar.gz
-
源码包安装:
- 如果有 README、readme 文件, 参考安装。
- ./configure 检查安装环境,生成 makefile 文件。
- make 生成 .o 文件 和 可执行文件。
- sudo make install 将必要的资源, 拷贝至系统指定目录。
-
测试是否安装成功:
-
进入 sample 目录中, 编译 .c 文件, 运行。
-
编译时,务必添加 指定库名的 选项 -levent
gcc hello-world.c -o hello -levent
-
安装成功后, 会在 系统的 /usr/local/lib 目录下,多出 libevent.so 和 libevent.a 库文件。
-
如果运行 ./hello-world 可执行文件,报出如下错误: error while loading shared libraries: libevent-2.1.so.6: cannot open shared object file: No such file or directory
-
解决方法
-
将库目录添加到 /etc/ld.so.cache 文件中
sudo vim /etc/ld.so.conf 文件,加入库所在路径即 /usr/local/lib/执行 sudo ldconfig -v ,该命令会重建/etc/ld.so.cache 文件
-
- 编译成功后启动可执行程序,使用 nc 命令指定端口号为 9995,得到输出即为成功
-
2. libevent 框架
-
创建base,使用 event_base_new()
#include <event2/event.h> struct event_base *event_base_new(void); struct event_base *base = event_base_new();
-
创建事件对象 event
// 常规事件 event event_new();// 带缓冲区的事件 bufferevent bufferevent_socket_new();
-
添加事件到 base上
int event_add(struct event *ev, const struct timeval *tv);
-
循环监听事件满足
int event_base_dispatch(struct event_base *base); event_base_dispatch(base);
-
释放 base 和事件对象
void event_base_free(struct event_base *base); event_base_free(base);
3. 常规事件
1. 创建事件对象event
struct event *event_new(struct event_base *base,evutil_socket_t fd,shortwhat,event_callback_fn cb; void *arg);base: event_base_new() 返回值。fd: 绑定到 event对象上的 文件描述符what: fd 对应的监听事件 (read、write、expcet)EV_READ 监听 一次 读事件EV_WRITE 监听 一次 写事件EV_PERSIST 持续触发。 结合 event_base_dispatch 函数使用。 保证持续循环。可以使用 “|” 连接。EV_PERSIST|EV_READ 或 EV_PERSIST|EV_WRITEcb: 一旦,事件满足监听条, 回调的函数。typedef void (*event_callback_fn)(evutil_socket_t fd, short, void *)arg: 回调函数的参数。返回值:成功创建的 事件对象
2. 添加、销毁事件对象event
// 添加事件
int event_add(struct event *ev, const struct timeval *tv);ev: event_new() 的返回值。 ————【注意】不是 event_base !!!tv: 通常 NULL // 销毁事件
int event_free(struct event *ev);成功: 0, 失败: -1
3.编码实现读写 fifo
read_fifo.c
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <event2/event.h>
#include <strings.h>void read_cb(evutil_socket_t fd, short what, void* arg)
{char buf[BUFSIZ];bzero(buf,sizeof(buf));read(fd, buf, sizeof(buf));printf("what:%s, read:%s\n",what & EV_READ ? "read YES" : "read NO", buf);sleep(1);
}int main()
{unlink("myfifo");mkfifo("myfifo", 0664);int fd = open("myfifo",O_RDONLY|O_NONBLOCK);//创建basestruct event_base* base = event_base_new();//创建事件//struct event *event_new(struct event_base *base,evutil_socket_t fd,short
//what,event_callback_fn cb; void *arg);struct event* ev = event_new(base, fd, EV_READ|EV_PERSIST, read_cb, NULL);//添加事件event_add(ev, NULL);//循环监听event_base_dispatch(base);//释放事件和baseevent_base_free(base);event_free(ev);return 0;
}
write_fifo.c
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <event2/event.h>
#include <string.h>void read_cb(evutil_socket_t fd, short what, void* arg)
{char buf[] = "hello libevent";write(fd, buf, strlen(buf)+1);sleep(1);
}int main()
{int fd = open("myfifo",O_WRONLY|O_NONBLOCK);//创建basestruct event_base* base = event_base_new();//创建事件//struct event *event_new(struct event_base *base,evutil_socket_t fd,short
//what,event_callback_fn cb; void *arg);struct event* ev = event_new(base, fd, EV_WRITE|EV_PERSIST, read_cb, NULL);//添加事件event_add(ev, NULL);//循环监听event_base_dispatch(base);//释放事件和baseevent_base_free(base);event_free(ev);return 0;
}
4. 一个小的函数
event_base_get_method(base); 函数可以返回当前base使用的多路IO转接方式
4. 事件的未决和非未决态
未决态:事件有资格被处理, 尚未被处理。
非未决态:事件没有资格被处理。
5. 带缓冲的事件bufferevent
1. bufferevent 特性
- 读缓冲:有数据 ——> 读回调函数会被调用 ——> 使用 bufferevent_read() (顶替 read() )——> 读数据
- 写缓冲:使用 bufferevent_write() ( 顶替 write() ) ——> 向 写缓冲,写数据 ——> 写缓冲中,一旦有数据,会自动刷新(写出给对端)——> 写完, 回调函数会被调用。
2. 创建、释放bufferevent
- 创建 bufferevent
struct bufferevent *bufferevent_socket_new(struct event_base *base,evutil_socket_t fd, enum bufferevent_options options);base: struct event_base ———— “base底座”fd: 要封装到 bufferevent 内的 fd options:BEV_OPT_CLOSE_ON_FREE。 作用:释放 bufferevent对象时, 同时释放内部封装的资源。【注意】:bufferevent_socket_new函数内,没有指定 fd 对应的 回调函数。
- 释放 bufferevent
void bufferevent_free(struct bufferevent *bev);bev:bufferevent_socket_new 函数的返回值。
3. 给bufferevent设置回调函数
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 写缓冲,对应的回调。 ———— 通常 NULL如: write_cb(){ 给调用者,发送写成功的“通知” }eventcb: 设置事件回调。 ———— 通常 NULL对应: BEV_EVENT_CONNECTED:———— 用作客户端。cbarg:上述回调函数的参数。
1. readcb对应的回调函数类型
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);
2. writecb对应的回调函数类型
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void * ctx);
// 示例:
void write_cb(struct bufferevent *bev, void *cbarg)
{.....数据写完了,这个函数才会被调用!!!
}
// bufferevent_write 函数原型
int bufferevent_write(struct bufferevent *bev, const void *buf, size_t size);
3. eventcb对应的回调函数类型
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *cbarg);
// 示例:
void event_cb(struct bufferevent *bev, short events, void *cbarg)
{events: BEV_EVENT_CONNECTED:———— 用作客户端。.....当有状态、特殊状况产生时,该回调函数会被调用。
}
4. 启用、禁用bufferevent缓冲区
- 默认:
- write 缓冲是 enable
- read 缓冲 是 disable。 —— 不能直接使用 bufferevent_read(); 读取数。
- 启用
void bufferevent_enable(struct bufferevent *bufev, short events); 启用缓冲区bufev: bufferevent_socket_new() 函数的返回值events: EV_READ、EV_WRITE、EV_READ|EV_WRITE 对应读和写缓冲区的启用
- 禁用
void bufferevent_disable(struct bufferevent *bufev, short events);
5. 借助bufferevent实现C/S通信
client端
原来:socket(); connect(); 现在 socket() + bufferevent_socket_connect()
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);bev: bufferevent_socket_new() 函数的返回值address/addrlen: 等同与 connect() 参2、3
server端
原来:socket(); bind(); listen(); accept(); 现在:evconnlistener_new_bind()
// 这一个函数,相当于 socket(); bind(); listen(); accept(); 的作用。
#include <event2/listener.h>
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:struct event_base --- “底座”cb:回调函数一旦,该函数被回调,说明客户端已经成功连接。回调函数内部,应与客户端进行数据通信。ptr:回调函数的参数flags:LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLEbacklog:listen 函数的2参。 -1 表最大值。sa: 服务端自己的地址结构socklen: 服务端自己的地址结构的大小。返回值:成功创建的监听器。
监听器 回调函数
typedef void (*evconnlistener_cb) (struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr,int len,void *ptr);
【注】:该回调函数,不由我们调用,是框架自动调用。因此,只需知晓参数含义即可。
释放监听服务器
void evconnlistener_free(struct evconnlistener *lev);
6. 使用libevent库实现C/S模型
1. 服务器端代码流程:
-
创建 base
-
绑定地址结构 用于 evconnlistener_new_bind() 函数创建监听器的传参
-
创建监听器 evconnlistener_new_bind()
监听器的回调函数用于进行通信,进行通信要使用 bufferevent 来监听读写和事件,所以 bufferevent的创建要在监听器的回调函数中。以下是创建监听器时的回调函数:
-
创建 bufferevent 事件 bufferevent_socket_new()
-
设置回调函数 bufferevent_setcb()
-
启动读回调 bufferevent_enable()
- 读回调:使用 bufferevent_read() 读取客户端发送来的数据并处理,处理后使用 bufferevent_write() 写回
- 写回调:bufferevent_write() 函数执行完毕后调用,无卵用
- 事件回调:通过判断 events & BEV_EVENT_EOF 可知客户端断开连接,events & BEV_EVENT_ERROR 可知有其他错误发生,这时直接调用 bufferevent_free() 释放 bufferevent
-
-
event_base_dispatch() 启动循环监听
-
释放监听器资源,释放base
2. 客户端代码流程:
- socket() 函数创建 通信套接字cfd
- 设置服务器的地址结构 srv_addr
- 创建base
- 创建bufferevent事件 bufferevent_socket_new()
- 设置回调函数 bufferevent_setcb() ,启动读回调 bufferevent_enable()
- 读回调:使用 bufferevent_read() 接收服务器发送来的消息,并在屏幕打印
- 写回调:打印说明写事件完成,写回调的打印信息应该紧接在 bufferevent_write() 之后
- 事件回调:(BEV_EVENT_CONNECTED & events) 为真时表示与服务器连接成功,可以使用事件回调来释放bufferevent的资源
- 与服务器建立连接,bufferevent_socket_connect()
- 创建普通事件 event 来监听从屏幕获取字符串的事件,将获取的字符串通过 bufferevent_write() 发送给对端
- 将 event 添加到 base中 event_add()
- 启动循环监听 event_base_dispatch()
- 释放base ,释放 event
3. 代码实现
服务器端
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>#define PORT 8000void read_cb(struct bufferevent *bev, void *cbarg)
{char buf[BUFSIZ];int n = bufferevent_read(bev, buf, sizeof(buf));for(int i=0 ;i<n ;++i){buf[i] = toupper(buf[i]);}write(STDOUT_FILENO, buf, n);bufferevent_write(bev, buf, n);sleep(1);
}void write_cb(struct bufferevent *bev, void* cbarg)
{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");}bufferevent_free(bev); printf("buffevent 资源已经被释放...\n");
}//用于客户端连接上后的通信
void listen_cb(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *ptr)
{//char cltip[16];//printf("client accept ip:%s, port%d\n",// inet_ntop(AF_INET, (struct sockaddr_in*)addr->sin_addr.s_addr, cltip, sizeof(cltip)),// htons((struct sockaddr_in*)addr->sin_port));struct event_base* base = (struct event_base*)ptr;//创建bufferevent事件struct bufferevent* bev = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);//设置回调bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);//启动读写缓冲区bufferevent_enable(bev, EV_READ|EV_WRITE);
}int main()
{struct sockaddr_in srv_addr;srv_addr.sin_family = AF_INET;srv_addr.sin_port = htons(PORT);srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//创建basestruct event_base* base = event_base_new();//创建监听器struct evconnlistener* listener = evconnlistener_new_bind(base, listen_cb, (void*)base, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (struct sockaddr*)&srv_addr, sizeof(srv_addr));//循环监听event_base_dispatch(base);//释放event_base_free(base);evconnlistener_free(listener);return 0;
}
客户端
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <arpa/inet.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>#define PORT 8000void read_cb(struct bufferevent* bev, void *cbarg)
{char buf[BUFSIZ];int n = bufferevent_read(bev, buf, sizeof(buf));buf[n] = '\0';printf("服务器say: %s", buf);bufferevent_write(bev, buf, n); //将数据再写回服务器,做出一直发送的效果
}void write_cb(struct bufferevent* bev, void *cbarg)
{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 )
{struct bufferevent* bev = (struct bufferevent*)arg;char buf[BUFSIZ];int n = read(fd, buf, sizeof(buf));bufferevent_write(bev, buf, n);sleep(1);
}int main()
{int cfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in srv_addr;srv_addr.sin_family = AF_INET;srv_addr.sin_port = htons(PORT);inet_pton(AF_INET, "127.0.0.1", &srv_addr.sin_addr.s_addr);//创建basestruct event_base* base = event_base_new();struct bufferevent* bev; //创建befferevent事件bev = bufferevent_socket_new(base, cfd, BEV_OPT_CLOSE_ON_FREE);//设置回调bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);//启用读缓冲区bufferevent_enable(bev, EV_READ|EV_WRITE);//连接服务器bufferevent_socket_connect(bev, (struct sockaddr*)&srv_addr, sizeof(srv_addr));struct event* ev = event_new(base, STDOUT_FILENO, EV_READ|EV_PERSIST, read_terminal, bev);//添加事件/vent_add(ev, NULL);//循环监听event_base_dispatch(base);//释放bufferevent事件event_free(ev);//释放baseevent_base_free(base);return 0;
}
7. some small point
有关管道读写注意:当写端关闭,读端还在读的时候,无论阻塞和非阻塞read都会返回0,表示对端关闭
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 基于FFmpeg4.1的视频播放器的极简实现(音视频学习笔记四)
前言 这篇文章记录一个简单视频播放器的开发过程,代码极其为简洁,基于ffmpeg最新版本4.1实现的。视频渲染用的SDL2.0,SDL视频渲染部分代码直接copy的雷神的最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)但是他这篇的代码对于高版本的ffmpeg已经不适配了。 运行结…...
2024/4/29 5:23:16 - Linux shell常用脚本命令
文章目录楔子1 xargs1.1 查找拷贝文件|查找解压文件`-n -f 参数解释` 可以参考 [ 阮一峰 xargs 命令教程](http://www.ruanyifeng.com/blog/2019/08/xargs-tutorial.html)复制创建文件夹3 文件重命名3.2 替换为日期文件批量杀死进程find查找并删除date找出最大的10个文件linu…...
2024/4/29 5:23:11 - 剑指Offer04:二维数组中的查找
题目描述:解法1:暴力破解法,直接两个for循环遍历所有二维数组所有元素,如果发现有包含该整数,返回true,否则,返回false。但是这种方法效率很低,不建议使用。 解法2:因为题目有说每一行从左到右递增排序,每一列都是从上到下递增排序。因此我们可以通过判断目标整数,是…...
2024/4/29 5:23:02 - 啥? 机器人要像人类一样学知识? 道翰天琼认知智能机器人平台API接口大脑为您揭秘。
啥? 机器人要像人类一样学知识? 道翰天琼认知智能机器人平台API接口大脑为您揭秘。编者按:2020 年 8 月 7 日,全球人工智能和机器人峰会(CCF-GAIR 2020)正式开幕。CCF-GAIR 2020 峰会由中国计算机学会(CCF)主办,香港中文大学(深圳)、雷锋网联合承办,鹏城实验室、深…...
2024/4/29 5:22:54 - 劲爆!周鸿祎的大战略!道翰天琼认知智能机器人平台API接口大脑为您揭秘。
劲爆!周鸿祎的大战略!道翰天琼认知智能机器人平台API接口大脑为您揭秘。2020伊始,伴随一系列新基建政策的落地,各行各业都加快了数字化转型的步伐。在周鸿祎看来,新基建本质是数字化基建,其重要应用场景是数字城市和工业互联网,前者不断提高城市治理水平,后者推动制造业…...
2024/5/5 6:58:15 - CCF-GAIR 2020 全球峰会来啦!道翰天琼认知智能机器人平台API接口大脑为您揭秘。
CCF-GAIR 2020 全球峰会来啦!道翰天琼认知智能机器人平台API接口大脑为您揭秘。于 2020 年 8 月 7 日-9 日召开的 2020 全球人工智能和机器人峰会(CCF-GAIR 2020)今日正式开幕。CCF-GAIR 2020 峰会由中国计算机学会(CCF)主办,香港中文大学(深圳)、雷锋网联合承办,鹏城…...
2024/4/28 21:35:14 - Linux进程讲解--操作系统/task_struct/僵尸状态/孤儿状态/IO信息&记账信息/进程优先级(PR)/fork/虚拟地址空间/ 分页式...
1 进程 冯诺依曼体系结构 冯诺依曼:计算机之父,在物理、化学、数学、也具有很大贡献,开始是研究原子弹的。 冯诺依曼体系结构图:关于冯诺依曼,必须强调几点:这里的存储器指的是内存,且所有数据在内存中存储的时候,采用2进制的方式进行存储; 不考虑缓存情况,这里的cpu…...
2024/4/29 5:22:45 - TiDB 在知乎万亿量级业务数据下的实践和挑战
一、业务场景知乎从问答起步,在过去的 8 年中逐步成长为一个大规模的综合性知识内容平台,目前,知乎上有多达 3000 万个问题,共收获了超过 1.3 亿个回答,同时知乎还沉淀了数量众多的文章、电子书以及其他付费内容,目前注册用户数是 2.2 亿,这几个数字还是蛮惊人的。我们有…...
2024/5/4 21:02:06 - js设计模式
文章目录面向对象特性为什么有面向对象?六大原则solid:1. 单一原则single responsibility2. 里氏替换原则liskov substitution(LSP)3. 依赖倒置原则dependence inversion4. 接口隔离原则interface segregation5. 迪米特原则/最小知晓原则law of demeter(LOD)6. 开闭原则o…...
2024/4/29 5:22:35 - 浅谈对JavaScript中闭包的理解
前 言 在前端开发中闭包是一个很重要的知识点,是面试中一定会被问到的内容。一、闭包的定义函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建…...
2024/4/29 5:22:24 - 01【基础】第一天 JavaScript - 【变量】编程定义, 计算机组成,JS定义及组成,变量,数据类型
第一天【变量】一,计算机编程基础目标:编程语言 / 计算机基础1. 编程语言1.1 编程编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的…...
2024/4/29 5:22:38 - python 对比两张图片
python 对比两张图片的相似度 def image_contrast(result, compare): # 比较两张图片的相似度""":param result: 参照图:param compare: 对比图:return: """image1 = Image.open(result)image2 = Image.open(compare)h1 = image1.histogram()h2…...
2024/4/29 3:02:35 - 如何在服务器中搭建属于自己的个人网盘
如何在服务器中搭建属于自己的个人网盘 为了这个博客,作者一天之内把服务器重装了5遍系统,请送上素质三连呗。 废话少说,附上搭建过程: 准备工作 1.准备一个Windows服务器 2.准备可道云服务器源文件 3.准备并安装好Windows宝塔 4.安装宝塔内的PHP54、MySQL等软件 5.配置好服…...
2024/4/29 5:22:22 - 微信小程序开发API封装
微信小程序开发API封装 .方法封装(新建文件夹util,工具文件,在文件夹下创建request.js文件,用于对方法封装) var app = getApp(); //项目URL相同部分,减轻代码量,同时方便项目迁移 //这里因为我是本地调试,所以host不规范,实际上应该是你 //备案的域名信息var host = …...
2024/4/29 5:22:15 - 线程和进程的面试题目
1 线程生命周期线程的生命周期包含5个阶段,包括:新建,就绪,运行,阻塞,销毁(终止)。新建:就是刚使用new方法,new出来的线程;就绪:就是调用的线程的start()方法后,这时候线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;运行:当就绪的线程被调度并获得C…...
2024/4/29 5:22:08 - 启动hadoop时,免密码登录引发的错误:“The authenticity of host ‘node01 (192.168.1.8)‘ can‘t be established.”
The authenticity of host ‘node01 (192.168.1.8)’ can’t be established. 详细报错: [root@node01 hadoop-2.7.5]# sbin/start-yarn.sh starting yarn daemons starting resourcemanager, logging to /export/servers/hadoop-2.7.5/logs/yarn-root-resourcemanager-node01…...
2024/4/29 5:22:04 - Ubuntu 自带的 vi 编辑器不好用解决方法
本来安装完ubantu还好好的可以使用vi编辑器,第二次就有点操作乱套的感觉了,删除键不好用,按上下左右的时候ABCD满天飞。本文引用别人的方法。已根据博客内容编辑修改测试可行,特此装载分享,望更多的人可以解决次问题。 https://blog.csdn.net/qq_36792209/article/details…...
2024/4/29 5:22:14 - 只需4步,自己搞个 Spring Boot Starter !
引言 只要你用Springboot,一定会用到各种spring-boot-starter。其实写一个spring-boot-starter ,仅需4步。下面我们就写一个starter,它将实现,在日志中打印方法执行时间。 第一步 创建maven项目 在使用spring-boot-starter,会发现,有的项目名称是 XX-spring-boot-starter…...
2024/4/29 5:22:32 - 第7章 类
定义抽象数据类型 类的基本思想:数据抽象和封装; 数据抽象:一种依赖于接口和实现分离的编程技术; 类的接口:用户所能执行的操作; 类的实现:类的数据成员,负责接口实现的函数体,定义类所需的各种私有函数; 封装:实现类的接口和实现分离;类的用户只能访问接口,不能访…...
2024/4/29 5:21:53 - 聚簇索引和非聚簇索引总结
什么是聚合索引(clustered index) / 什么是非聚合索引(nonclustered index)? 聚合索引和非聚合索引有什么区别?深入浅出理解索引结构 https://www.cnblogs.com/sunliyuan/p/5826419.html 聚簇索引的优势和劣势 https://www.jianshu.com/p/fa8192853184 一: 深入浅出理解索引…...
2024/4/29 5:21:54
最新文章
- A Bug‘s Life (并查集)
//新生训练 #include <iostream> #include <algorithm> using namespace std; const int N 5000; int p[N], sz[N]; int n, m; int find(int x) {if (p[x] ! x)p[x] find(p[x]);return p[x]; } int main() {int T;scanf("%d", &T);for (int k 1; …...
2024/5/5 12:34:17 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 阿里云8核32G云服务器租用优惠价格表,包括腾讯云和京东云
8核32G云服务器租用优惠价格表,云服务器吧yunfuwuqiba.com整理阿里云8核32G服务器、腾讯云8核32G和京东云8C32G云主机配置报价,腾讯云和京东云是轻量应用服务器,阿里云是云服务器ECS: 阿里云8核32G服务器 阿里云8核32G服务器价格…...
2024/5/5 8:42:13 - ADB(Android Debug Bridge)操作命令详解及示例
ADB(Android Debug Bridge)是一个强大的命令行工具,它是Android SDK的一部分,主要用于Android设备(包括真实手机和平板电脑以及模拟器)的调试、系统控制和应用程序部署。 下面是一些ADB的常用命令ÿ…...
2024/5/5 8:28:21 - 416. 分割等和子集问题(动态规划)
题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满ÿ…...
2024/5/4 12:05:22 - 【Java】ExcelWriter自适应宽度工具类(支持中文)
工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...
2024/5/5 12:22:20 - Spring cloud负载均衡@LoadBalanced LoadBalancerClient
LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...
2024/5/4 14:46:16 - TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案
一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...
2024/5/4 23:54:44 - VB.net WebBrowser网页元素抓取分析方法
在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...
2024/5/4 12:10:13 - 【Objective-C】Objective-C汇总
方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...
2024/5/4 23:54:49 - 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...
2024/5/4 23:54:44 - 【ES6.0】- 扩展运算符(...)
【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数࿰…...
2024/5/4 14:46:12 - 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?
文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...
2024/5/4 14:46:11 - Go语言常用命令详解(二)
文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...
2024/5/4 14:46:11 - 用欧拉路径判断图同构推出reverse合法性:1116T4
http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai 和 a i 1 a_{i1} ai1 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然࿰…...
2024/5/5 2:25:33 - 【NGINX--1】基础知识
1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...
2024/5/4 21:24:42 - Hive默认分割符、存储格式与数据压缩
目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...
2024/5/4 12:39:12 - 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法
文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...
2024/5/4 13:16:06 - --max-old-space-size=8192报错
vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...
2024/5/4 16:48:41 - 基于深度学习的恶意软件检测
恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...
2024/5/4 14:46:05 - JS原型对象prototype
让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...
2024/5/5 3:37:58 - C++中只能有一个实例的单例类
C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...
2024/5/4 23:54:30 - python django 小程序图书借阅源码
开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图࿰…...
2024/5/4 9:07:39 - 电子学会C/C++编程等级考试2022年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...
2024/5/4 14:46:02 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57