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

stm32 lwip tcp服务端频繁接收连接失效问题解决(tcp_recved)

一、问题描述

最近用stmf429单片机作为TCP服务端遇到一个问题,就是客户端特别频繁的发送消息,过一段时间以后,客户端的请求不再被客户端接收到,而且服务器端监控的掉线回调函数也不会被调用,好像这个连接就凭空的消失了。

二、问题排除

首先,我以为是QT的客户端出现问题了,因为请求过于频繁,所以tcp的发送缓存区满了,但是我在发送消息的时候加了缓存区内容判断,有内容就不发送,还是不管用,然后用了串口助手软件以同样速度向单片机发送消息,过不了多久也就失去连接了,所以排除了客户端的问题。确定是单片机服务器端的问题,然后我又改了服务器端的返回消息那里,也是加发送缓存区的判断,同样是不管用,最后发现,是没有加tcp_recved的原因。

三、 tcp_recved描述

tcp_recved是 lwIP(Lightweight IP,轻量级 TCP/IP 协议栈)中用于 TCP 连接的数据接收确认操作的重要函数调用。

1.函数作用

tcp_recved 函数的主要作用是告知 lwIP 协议栈,应用程序已经成功处理了指定长度的数据,这样 lwIP 可以更新接收窗口的大小,允许发送方继续发送更多的数据。在 TCP 协议中,接收方会维护一个接收窗口,用于告知发送方自己当前能够接收的数据量。当应用程序处理完一部分数据后,需要调用 tcp_recved 函数来调整这个窗口大小,以保证数据的正常传输。

2.函数原型及参数

void tcp_recved(struct tcp_pcb *tpcb, u16_t len);
  • 参数
    • tpcb:指向 struct tcp_pcb 类型的指针,该结构体代表一个 TCP 连接的协议控制块,包含了该连接的所有状态信息。
    • len:表示应用程序已经成功处理的数据长度,单位是字节。

3. 使用场景

在 TCP 服务器或客户端的接收回调函数中,当应用程序接收到数据并完成处理后,需要调用 tcp_recved 函数。例如,在 client_recv_handler 回调函数中,当处理完接收到的 pbuf(数据包缓冲区)中的数据后,就会调用该函数。

4.实现原理

  • 更新接收窗口tcp_recved 函数会根据传入的 len 参数,更新 TCP 连接的接收窗口大小。接收窗口的大小表示接收方当前还能接收多少字节的数据。当应用程序处理完数据后,接收窗口会相应地增大,允许发送方发送更多的数据。
  • 发送确认信息:lwIP 会根据更新后的接收窗口信息,向发送方发送确认信息(ACK),告知发送方可以继续发送的数据范围。

4.示例代码

#include "lwip/tcp.h"// 接收回调函数
err_t client_recv_handler(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{if (p != NULL) {// 处理接收到的数据// 这里可以添加具体的数据处理逻辑,如解析数据、存储数据等// ...// 告知 lwIP 已经处理完这些数据tcp_recved(tpcb, p->tot_len);// 释放 pbuf 占用的内存pbuf_free(p);} else if (err == ERR_OK) {// 连接关闭处理tcp_close(tpcb);}return ERR_OK;
}

5.注意事项

  • 及时调用:在处理完接收到的数据后,应及时调用 tcp_recved 函数,否则接收窗口不会更新,发送方可能会认为接收方没有足够的空间来接收新的数据,从而暂停数据发送,导致网络性能下降,我这次就是因为没有调用这个函数,客户端与服务器端频繁通讯出现了连接失效的问题。
  • 数据长度准确:传入 tcp_recved 函数的 len 参数必须准确表示应用程序已经处理的数据长度,否则可能会导致接收窗口大小计算错误,影响数据的正常传输。
  • 内存管理:在调用 tcp_recved 函数后,通常需要释放 pbuf 占用的内存,避免内存泄漏。可以使用 pbuf_free 函数来释放内存。

四、TCP服务端完整代码

#include "tcp_demo.h"
extern u8* GETDATA_BUFF8;
extern short *GETDATA_BUFF16;
extern u8 nowtype;extern OS_SEM	Gather_SEM;#define TCP_SERVER_PORT 8088  // 定义TCP服务器监听的端口号,可按需修改
#define MAX_CONNECTIONS 2      // 最大允许同时连接的客户端数量
#define RX_BUFFER_SIZE 1024    // 接收缓冲区大小// 用于存储客户端连接的结构体数组
struct tcp_pcb *tcp_server_pcbs[MAX_CONNECTIONS];// 用于保护对tcp_server_pcbs数组操作的互斥信号量
OS_SEM tcp_server_pcbs_sem;// 处理客户端连接的函数
err_t client_connection_handler(void *arg, struct tcp_pcb *newpcb, err_t err);
// 处理客户端接收数据的函数
err_t client_recv_handler(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
// 处理客户端发送数据的函数(示例中简单回显数据给客户端)
err_t client_send_handler(void *arg, struct tcp_pcb *tpcb, u16_t len);
// 处理客户端断开连接的函数
void client_err_handler(void *arg, err_t err);
// TCP服务器任务函数
void tcp_server_task(void *p_arg);//TCP客户端任务
#define TCP_PRIO		7
//任务堆栈大小
#define TCP_STK_SIZE	300
//任务控制块
OS_TCB	TcpTaskTCB;
//任务堆栈
CPU_STK TCP_TASK_STK[TCP_STK_SIZE];int close_tcp=0;void tcp_server_task(void *p_arg)
{struct tcp_pcb *server_pcb;err_t err;OS_ERR os_err;// 创建一个TCP协议控制块(PCB)用于服务器端server_pcb = tcp_new();if (server_pcb == NULL){printf("Error creating TCP PCB\n");return;}// 绑定服务器的IP地址和端口号err = tcp_bind(server_pcb, IP_ADDR_ANY, TCP_SERVER_PORT);if (err!= ERR_OK){printf("Error binding TCP socket: %d\n", err);tcp_close(server_pcb);return;}// 将服务器PCB设置为监听状态,等待客户端连接server_pcb = tcp_listen(server_pcb);if (server_pcb == NULL){printf("Error listening for connections\n");tcp_close(server_pcb);return;}// 设置接受客户端连接的回调函数tcp_accept(server_pcb, client_connection_handler);while (1){// 任务可以在这里进行适当的阻塞等待,避免过度占用CPU资源OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_HMSM_STRICT,&os_err); //延时100ms}
}err_t client_connection_handler(void *arg, struct tcp_pcb *newpcb, err_t err)
{OS_ERR os_err;int client_index;if (err!= ERR_OK){return err;}// 获取互斥信号量,保护对tcp_server_pcbs数组的访问OSSemPend(&tcp_server_pcbs_sem,0,OS_OPT_PEND_BLOCKING,0,&os_err); 	//请求信号量if(tcp_server_pcbs[close_tcp]!=NULL){tcp_close(tcp_server_pcbs[close_tcp]);}tcp_server_pcbs[close_tcp]=newpcb;if(close_tcp==0){close_tcp=1;}else{close_tcp=0;}// 设置接收、发送和错误处理的回调函数tcp_recv(newpcb, client_recv_handler);tcp_sent(newpcb, client_send_handler);tcp_err(newpcb, client_err_handler);OSSemPost(&tcp_server_pcbs_sem, OS_OPT_POST_1, &os_err);return ERR_OK;
}err_t client_recv_handler(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{OS_ERR os_err;if (err == ERR_OK && p!= NULL){// 将接收到的pbuf数据复制到本地缓冲区(这里简单示例,可优化)/**char rx_buffer[RX_BUFFER_SIZE];int copied_bytes = 0;struct pbuf *q = p;while (q!= NULL){int bytes_to_copy = (q->len < (RX_BUFFER_SIZE - copied_bytes))? q->len : (RX_BUFFER_SIZE - copied_bytes);memcpy(&rx_buffer[copied_bytes], q->payload, bytes_to_copy);copied_bytes += bytes_to_copy;q = q->next;}**/// 这里可以对接收到的数据进行处理,比如根据协议解析等,现在简单回显数据给客户端//tcp_write(tpcb, rx_buffer, copied_bytes, TCP_WRITE_FLAG_COPY);//tcp_output(tpcb);OSSemPend(&Gather_SEM,0,OS_OPT_PEND_BLOCKING,0,&os_err); 	//请求信号量u16_t free_space = tcp_sndbuf(tpcb);if (free_space >= 1441) {// 缓冲区有足够空间,写入数据tcp_write(tpcb, GETDATA_BUFF8, 1441, TCP_WRITE_FLAG_COPY);tcp_output(tpcb);} else {// 缓冲区空间不足,进行相应处理,如等待或丢弃数据// 这里简单打印提示信息printf("Send buffer is not enough!\n");}OSSemPost (&Gather_SEM,OS_OPT_POST_1,&os_err);				//发送信号量// 释放接收到的pbuf内存tcp_recved(tpcb, p->tot_len);pbuf_free(p);}else if (err == ERR_OK && p == NULL){OSSemPend(&tcp_server_pcbs_sem,0,OS_OPT_PEND_BLOCKING,0,&os_err); 	//请求信号量// 客户端关闭了连接,正常处理for (int i = 0; i < MAX_CONNECTIONS; i++){if (tcp_server_pcbs[i] == tpcb){tcp_server_pcbs[i] = NULL;break;}}OSSemPost(&tcp_server_pcbs_sem, OS_OPT_POST_1, &os_err);tcp_close(tpcb);}else{// 出现错误情况,关闭连接tcp_close(tpcb);}return ERR_OK;
}err_t client_send_handler(void *arg, struct tcp_pcb *tpcb, u16_t len)
{// 这里可以根据实际发送情况做一些后续处理,当前示例只是简单回显,无需额外操作return ERR_OK;
}void client_err_handler(void *arg, err_t err)
{struct tcp_pcb *tpcb = (struct tcp_pcb *)arg;OS_ERR os_err;// 获取互斥信号量,保护对tcp_server_pcbs数组的访问OSSemPend(&tcp_server_pcbs_sem,0,OS_OPT_PEND_BLOCKING,0,&os_err); 	//请求信号量for (int i = 0; i < MAX_CONNECTIONS; i++){if (tcp_server_pcbs[i] == tpcb){tcp_server_pcbs[i] = NULL;break;}}OSSemPost(&tcp_server_pcbs_sem, OS_OPT_POST_1, &os_err);tcp_close(tpcb);
}//创建TCP线程
//返回值:0 TCP创建成功
//		其他 TCP创建失败
u8 tcp_demo_init(void)
{OS_ERR err;CPU_SR_ALLOC();OS_CRITICAL_ENTER();//进入临界区//创建TCP任务OSTaskCreate((OS_TCB 	* )&TcpTaskTCB,		(CPU_CHAR	* )"tcp task", 		(OS_TASK_PTR )tcp_server_task, 			(void		* )0,					(OS_PRIO	  )TCP_PRIO,     (CPU_STK   * )&TCP_TASK_STK[0],	(CPU_STK_SIZE)TCP_STK_SIZE/10,	(CPU_STK_SIZE)TCP_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					(void   	* )0,					(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR 	* )&err);OS_CRITICAL_EXIT();	//退出临界区return err;
}

 

1. 全局变量和宏定义

  • 端口和连接相关
    • TCP_SERVER_PORT:定义了 TCP 服务器监听的端口号,这里设为 8088。
    • MAX_CONNECTIONS:规定了服务器最大允许同时连接的客户端数量,为 2。
    • RX_BUFFER_SIZE:设置了接收缓冲区的大小,为 1024 字节。
  • 客户端连接数组和信号量
    • tcp_server_pcbs:是一个用于存储客户端连接的 struct tcp_pcb 类型的数组,长度为 MAX_CONNECTIONS
    • tcp_server_pcbs_sem:用于保护对 tcp_server_pcbs 数组操作的互斥信号量。
  • 其他外部变量GETDATA_BUFF8GETDATA_BUFF16nowtype 是外部定义的变量,Gather_SEM 是一个外部信号量。

2. 函数声明

声明了多个处理 TCP 连接、数据接收、发送、错误处理以及服务器任务的函数,具体如下:

  • client_connection_handler:处理客户端连接请求。
  • client_recv_handler:处理客户端发送的数据。
  • client_send_handler:处理数据发送完成后的操作。
  • client_err_handler:处理连接错误。
  • tcp_server_task:TCP 服务器的主任务函数。

3. TCP 服务器任务函数 tcp_server_task

  • 创建和绑定 PCB:使用 tcp_new() 创建一个 TCP 协议控制块(PCB),并通过 tcp_bind() 将其绑定到指定的 IP 地址(IP_ADDR_ANY 表示监听所有可用的 IP 地址)和端口号。
  • 监听连接:调用 tcp_listen() 将服务器 PCB 设置为监听状态,等待客户端连接。
  • 设置回调函数:使用 tcp_accept() 设置接受客户端连接的回调函数为 client_connection_handler
  • 任务循环:在一个无限循环中,使用 OSTimeDlyHMSM() 函数进行 100ms 的延时,避免任务过度占用 CPU 资源。

4. 客户端连接处理函数 client_connection_handler

  • 错误检查:检查连接是否存在错误,若有则直接返回错误码。
  • 管理连接数组:获取互斥信号量 tcp_server_pcbs_sem,保护对 tcp_server_pcbs 数组的访问。如果数组中已有连接,关闭该连接,然后将新的连接添加到数组中。
  • 设置回调函数:为新的客户端连接设置接收、发送和错误处理的回调函数,分别为 client_recv_handlerclient_send_handler 和 client_err_handler
  • 释放信号量:操作完成后,释放互斥信号量。

5. 客户端数据接收处理函数 client_recv_handler

  • 正常接收数据:当接收到数据(err == ERR_OK && p != NULL)时,先获取 Gather_SEM 信号量,检查发送缓冲区是否有足够空间。若空间足够,将 GETDATA_BUFF8 中的 1441 字节数据写入发送缓冲区并尝试发送;若空间不足,打印提示信息。处理完后释放 Gather_SEM 信号量,调用 tcp_recved() 告知 lwIP 已处理的数据长度,并释放接收到的 pbuf 内存。
  • 客户端关闭连接:当客户端关闭连接(err == ERR_OK && p == NULL)时,获取 tcp_server_pcbs_sem 信号量,从 tcp_server_pcbs 数组中移除该连接,然后释放信号量并关闭连接。
  • 错误处理:若出现其他错误情况,直接关闭连接。

6. 客户端数据发送处理函数 client_send_handler

该函数目前只是简单返回 ERR_OK,可根据实际发送情况添加后续处理逻辑。

7. 客户端连接错误处理函数 client_err_handler

获取 tcp_server_pcbs_sem 信号量,从 tcp_server_pcbs 数组中移除出现错误的连接,释放信号量并关闭连接。

8. TCP 任务创建函数 tcp_demo_init

使用 uC/OS-II 的 OSTaskCreate() 函数创建 tcp_server_task 任务,指定任务的优先级、堆栈等参数。如果任务创建成功,返回 0;否则返回相应的错误码。

 

 

相关文章:

stm32 lwip tcp服务端频繁接收连接失效问题解决(tcp_recved)

一、问题描述 最近用stmf429单片机作为TCP服务端遇到一个问题&#xff0c;就是客户端特别频繁的发送消息&#xff0c;过一段时间以后&#xff0c;客户端的请求不再被客户端接收到&#xff0c;而且服务器端监控的掉线回调函数也不会被调用&#xff0c;好像这个连接就凭空的消失…...

java项目之基于SSM会议管理系统的设计与实现源码(ssm+mysql)

项目简介 基于SSM会议管理系统的设计与实现实现了以下功能&#xff1a; 基于SSM会议管理系统的设计与实现的主要使用者分为&#xff1a;管理员登录后修改个人的密码。用户管理中&#xff0c;对公司内的用户进行管理&#xff0c;包括会议管理员和员工&#xff0c;管理部门信息…...

腿足机器人之二- 运动控制概览

腿足机器人之二运动控制概览 高层运动规划MPCRL 中层逆运动学和逆动力学底层执行器控制传感器校正 上一篇博客是腿足机器人的骨架和关节的机械和电气组件&#xff0c;关节不仅需要通过机械设计实现复杂的运动能力&#xff0c;还必须通过电子组件和控制系统来精确控制这些运动。…...

【MySQL】基础篇

1. MySQL中的NULL值是怎么存放的&#xff1f; MySQL的compact行格式中会用【NULL值列表】来标记值为NULL的列&#xff0c;NULL值不会存储在行格式中的真实数据部分。 NULL值列表会占用1字节空间&#xff0c;当表中所有字段都被定义成NOT NULL&#xff0c;行格式中就不会有NULL值…...

vscode环境搭建

目录 一、安装VSCode 二、安装Python 三、安装Anaconda&#xff08;可选&#xff0c;但推荐&#xff09; 四、安装深度学习相关库 五、配置VSCode 六、 结果可视化 一、安装VSCode 访问官网下载&#xff1a;从VSCode官方网站下载适合你操作系统的安装包。安装&#xff1a;运行安…...

tp whereOr用法2

有时候会用到多个whereOr 可以用闭包来完成查询 Db::name(table_name)->whereOr([[age,null,],[age,,]])->select();Db::name(table_name)->whereOr([[birthday,null,],[birthday,,]])->select();这两个是OR(或)关系 Db::name(table_name)->whereOr([[age,nul…...

前端面试题目---页面抖动的原因、如何避免、如何解决

前端页面抖动是一个常见且影响用户体验的问题&#xff0c;下面将从抖动发生的场景、解决办法以及预防措施三个方面进行详细阐述。 页面抖动发生的场景 1. 元素尺寸动态变化 图片加载&#xff1a;当页面中图片的宽高没有预先设定&#xff0c;在图片加载完成后&#xff0c;其实…...

Spring Boot整合DeepSeek实现AI对话(API调用和本地部署)

本篇文章会分基于DeepSeek开放平台上的API&#xff0c;以及本地私有化部署DeepSeek R1模型两种方式来整合使用。 本地化私有部署可以参考这篇博文 全面认识了解DeepSeek利用ollama在本地部署、使用和体验deepseek-r1大模型 Spring版本选择 根据Spring官网的描述 Spring AI是一…...

DeepSeek 的 API 服务引入 WPS Office

以下是将 DeepSeek 的 API 服务引入 WPS Office 的通用集成教程。以调用 DeepSeek 的 AI 功能&#xff08;如文本生成、数据分析&#xff09;为例&#xff0c;假设你需要通过 WPS 的宏或插件调用外部 API&#xff1a; 准备工作 注册 DeepSeek 账号并获取 API Key 访问 DeepSe…...

在Vue中,JavaScript数组常用方法,添加,插入,查找,删除等整理

在Vue中&#xff0c;JavaScript数组常用&#xff0c;添加&#xff0c;插入&#xff0c;查找&#xff0c;删除等整理 1.splice()方法可以直接修改原数组&#xff0c;通过指定要删除元素的索引来删除它。 例&#xff1a; let index // 要删除的元素的索引; this.array.splice(i…...

树莓派上 基于Opencv 实现人脸检测与人脸识别

一&#xff0c;需求 基于树莓派4b&#xff0c;usb1080p摄像头&#xff0c;实现人脸检测与人脸识别。尝试了海陵科的模组和百度的sdk。海陵科的模组无法录入人脸&#xff0c;浪费了100多块钱。百度的sdk 在树莓派上也无法录入人脸&#xff0c;官方解决不了。最后只能用opencv自…...

Unity 接入Tripo 文生模型,图生模型

官方网站&#xff1a;https://www.tripo3d.ai/app/home自行注册账号并且登陆下载Unity插件&#xff1a;https://cdn-web.tripo3d.ai/plugin/tripo-unity.zip申请apikey&#xff1a; https://platform.tripo3d.ai/api-keys使用&#xff08;后续过程就按照第二步下载的插件里面的…...

Redis常见数据结构

目录 基本介绍 特点&#xff1a; 全局命令 数据类型&#xff1a; String Hash List Set Zset 基本介绍 Redis是一个在内存中存储数据的中间件,可作为数据库&#xff0c;缓存&#xff0c;消息队列等。 特点&#xff1a; 持久化&#xff1a;Redis会把数据存储在内存中…...

fps动作系统9:动画音频

文章目录 音频单播放音频文件也是可以的&#xff0c;只不过是2d声音。创建音频蓝图cue(音效)音量乘数 衰减(空间效果)音量自然声音内部半径衰减距离 空间化双声道 绑定到动画动画序列轨道 音频 单播放音频文件也是可以的&#xff0c;只不过是2d声音。 创建音频蓝图 cue(音效…...

十四、GitLab 流水线自动化部署之 Windows Server

一、软件下载 本文章采用 Windows 版本的 Gitlab Runner 客户端&#xff0c;下载地址参考如下&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1nktWQGR4toRpgzEn9Qj3kQ?pwd0p1d 提取码&#xff1a;0p1d --来自百度网盘超级会员V7的分享 二、环境安装 1、Java 环境…...

数据库数据恢复—MongoDB丢失_mdb_catalog.wt文件导致报错的数据恢复案例

MongoDB数据库存储模式为文档数据存储库&#xff0c;存储方式是将文档存储在集合之中。 MongoDB数据库是开源数据库&#xff0c;同时提供具有附加功能的商业版本。 MongoDB中的数据是以键值对(key-value pairs)的形式显示的。在模式设计上&#xff0c;数据库受到的约束更少。这…...

mysql8.0使用MGR实现高可用与利用MySQL Router构建读写分离MGR集群

MGR是MySQL Group Replication的缩写&#xff0c;即MySQL组复制。 在以往&#xff0c;我们一般是利用MySQL的主从复制或半同步复制来提供高可用解决方案&#xff0c;但这存在以下几个比较严重的问题&#xff1a; 主从复制间容易发生复制延迟&#xff0c;尤其是在5.6以前的版本…...

基于Ubuntu2404搭建k8s-1.31集群

k8s 1.31 环境初始化安装Container安装runc安装CNI插件部署k8s集群安装crictl使用kubeadm部署集群节点加入集群部署Calico网络配置dashboard 本实验基于VMware创建的Ubuntu2404虚拟机搭建k8s 1.31版本集群&#xff0c;架构为一主一从&#xff0c;容器运行时使用Container&#…...

Golang的图形编程应用案例

Golang的图形编程应用案例 一、Golang的图形编程概述 是一种高效、可靠且易于使用的编程语言&#xff0c;具有并发性和简洁性&#xff0c;因此在图形编程领域也有着广泛的应用。Golang的图形编程主要通过各种图形库来实现&#xff0c;其中最知名的是Go图形库&#xff08;Ebiten…...

PostgreSQL 错误代码 23505 : ERROR: duplicate key value violates unique constraint

目录 1. 确认错误信息2. 检查数据3. 处理重复数据4. 检查唯一约束5. 添加唯一约束6. 使用事务处理并发操作7. 使用触发器8. 使用 ON CONFLICT 子句9. 重置序列10. 捕获异常并重试 错误代码 23505 是 PostgreSQL 中表示违反唯一约束&#xff08;unique violation&#xff09;的标…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...