STM32CubeMX-H7-19-ESP8266通信(中)--单片机控制ESP8266实现TCP地址通信

前言

        上篇文章我们已经能够使用串口助手实现esp8266的几种通信,接下来我们使用单片机控制实现。这篇文章会附带教程,增加.c和,.h,把串口和定时器放到对应的编号,然后调用初始化就可以使用了。

先讲解,然后末尾再放源码,也可以先看源码再看讲解

一.串口的不定时长接收

        因为esp8266发送的信息是没有帧头和帧位的,所以我们只能用这个方法,串口选定我们对应连接,我这里选择串口2,串口一用于重定向,打印调试信息(具体可以看我以前串口重定向的教程https://blog.csdn.net/m0_74211379/article/details/145366555?spm=1001.2014.3001.5502)。

        这里还需要使用一个1ms的定时器中断,这个方法也可以看我之前的文章https://blog.csdn.net/m0_74211379/article/details/146238875?spm=1001.2014.3001.5502

        然后开始讲用法

uint8_t esp8266_buffer[128],esp8266_buff[1],esp8266_len=0,esp8266_time=0,esp8266_flag=0;
char esp8266_wait[100];

这个是变量定义,全局的

要放在串口中断

void ESP8266_UART_Handler(void)
{esp8266_buffer[esp8266_len++]=esp8266_buff[0];esp8266_time=0;HAL_UART_Receive_IT(ESP8266_UART,(uint8_t *)esp8266_buff,1);
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART2)		{	 ESP8266_UART_Handler();}			
}

放在1ms定时器中断

void ESP8266_Time(void)
{esp8266_time++;if((esp8266_time>10)&&(esp8266_len>0)){esp8266_buffer[esp8266_len]=0;ESP8266_Change();memset(esp8266_buffer, '\0', sizeof(esp8266_buffer));esp8266_len=0;esp8266_time=0; } 
}void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM2){ESP8266_Time();}
}

 

处理获取一次的数据

void ESP8266_Change()
{printf("%s\r\n",esp8266_buffer);if(contains_OK(esp8266_buffer,esp8266_wait)){esp8266_flag=1;}ESP8266_IPD(esp8266_buffer);
}

二.WiFi名称密码还有TCP地址和端口号

const char ESP8266_WIFI_SSID[]="lty";
const char ESP8266_WIFI_PassWord[]="2395832518";
const char ESP8266_WIFI_TCP_IP[]="112.125.89.8";
const char ESP8266_WIFI_TCP_PORT[]="45655";

三.初始化

void ESP8266_Init(void)
{HAL_TIM_Base_Start_IT(ESP8266_TIM);HAL_UART_Receive_IT(ESP8266_UART,(uint8_t *)esp8266_buff,1);
}

四.发送指令函数

这里对需要连接的指令进行封装,第一个是发送的指令,第二个是接收到什么指令才能继续


void ESP8266_CMD(uint8_t cmd,uint16_t leng)
{char buffer[100];switch(cmd){case 0:sprintf(buffer,"AT+RST\r\n");sprintf(esp8266_wait,"OK");   break;case 1:sprintf(buffer,"AT\r\n");sprintf(esp8266_wait,"OK");break;	case 2:sprintf(buffer,"AT+CWMODE=1\r\n");sprintf(esp8266_wait,"OK");break;	case 3:sprintf(buffer,"AT+CWJAP=\"%s\",\"%s\"\r\n",ESP8266_WIFI_SSID,ESP8266_WIFI_PassWord);sprintf(esp8266_wait,"WIFI GOT IP");break;	case 4:sprintf(buffer,"AT+CWJAP?\r\n");sprintf(esp8266_wait,"OK");break;	case 5:sprintf(buffer,"AT+CIPMUX=0\r\n");sprintf(esp8266_wait,"OK");break;    case 6:sprintf(buffer,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",ESP8266_WIFI_TCP_IP,ESP8266_WIFI_TCP_PORT);sprintf(esp8266_wait,"OK");break;    case 7:sprintf(buffer,"AT+CIPSEND=%d\r\n",leng);sprintf(esp8266_wait,"");break;    case 8:sprintf(buffer,"");sprintf(esp8266_wait,"SEND OK");break;}ESP8266_commom(buffer);
}

五.等待发送指令函数

这个函数用于检测缓冲区是否有接收完成的指令,如果没有,那么超过200ms就会重新发送一次指令,直到缓冲区有接受到指令的字符串文本

void ESP8266_commom(const char *cmd)
{HAL_UART_Transmit(ESP8266_UART,(uint8_t *)cmd,strlen(cmd),100);esp8266_flag=0;while (esp8266_flag==0){if (esp8266_time>200){HAL_UART_Transmit(ESP8266_UART,(uint8_t *)cmd,strlen(cmd),100);printf("%s time out\r\n",cmd);esp8266_time=0;}}
}int contains_OK(const char *str, const char *substr) {if (strstr(str, substr) != NULL) {return 1; // 包含 }return 0; // 不包含 
}

六.连接上TCP

上面的弄好后,进行一次循环就可以连接上

void ESP8266_CONNECT_TO_TCP()
{for(uint8_t i = 0; i < 7; i++){  ESP8266_CMD(i,0);printf("cmd=%d\r\n",i);HAL_Delay(500);}
}

七.往TCP网络发送消息

也是对原有函数的封装,先获取要发送的长度,然后再发送

void ESP8266_send_TCP(const char *data)
{ESP8266_CMD(7,strlen(data));HAL_UART_Transmit(ESP8266_UART,(uint8_t *)data,strlen(data),100);ESP8266_CMD(8,0);
}

八.接收TCP发送来的消息

根据我实测的话,虽然串口显示第一个是+,但是打印显示是在后两个位置,所以我做一个偏移


void ESP8266_IPD(const char *data)
{char *p=data;uint8_t leng=0;char hand[256];if(strlen(data)>6)//printf("data[0]=%c,data[1]=%c,data[2]=%c,data[3]=%c,data[4]=%c\r\n",data[0],data[1],data[2],data[3],data[4]);if (data[2] == '+' && data[3] == 'I' && data[4] == 'P' && data[5] == 'D'){p+=6; while (*p != ':') {leng = leng * 10 + *p - '0';p++;	}p++; strncpy(hand, p, leng); hand[leng] = '\0'; printf("Received data: %s\r\n", hand);}
}

九.H文件的修改

把串口和定时器编号修改对九可以了

#ifndef HC_TR_H
#define HC_TR_H#include "main.h"#define ESP8266_UART    &huart2
#define ESP8266_TIM    &htim2
void ESP8266_Change();
void ESP8266_Time(void);
void ESP8266_Init(void);
void ESP8266_UART_Handler(void);
void ESP8266_CMD(uint8_t cmd,uint16_t leng);
int contains_OK(const char *str, const char *substr);
void ESP8266_commom(const char *cmd);
void ESP8266_CONNECT_TO_TCP();
void ESP8266_send_TCP(const char *data);
void ESP8266_IPD(const char *data);#endif /* HC_TR_H */

十.功能测试及使用教程

首先我们手机开热点,2.4G,5G的不行

根据网站合宙 TCP/UDP web工具 (luatos.com)

获取的填入

然后在主函数添加头文件后,直接写

初始化加连接WIFI,还有发送两次数据

	ESP8266_Init();
ESP8266_CONNECT_TO_TCP();
ESP8266_send_TCP("hello\r\n");
ESP8266_send_TCP("yes ok\r\n");

然后编译烧录

串口助手打印的数据

AT+RSTOK
WIFI DISCONNECTcmd=0
(5d6f877)
SPI Speed : 40MHz
SPI Mode : DOUT
SPI Flash Size & Map: 8Mbit(512KB+512KB)
jump to run user1 @ 1000?rls髇lreadyATtime out
AT
ATbusy p...OKcmd=1
AT+CWMODE=1time out
AT+CWMODE=1
AT+CWMODE=1busy p...OKcmd=2
AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"time out
AT+CWJAP="lty2","2395832518"busy p...
AT+CWJAP="lty2","2395832518"busy p...
AT+CWJAP="lty2","2395832518"busy p...
AT+CWJAP="lty2","2395832518"busy p...
AT+CWJAP
cmd=3
WIFI CONNECTEDAT+CWJAP?time out
AT+CWJAP?busy p...
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...WIFI GOT IPAT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...AT+CWJAP?time out
AT+CWJAP?busy p...OKcmd=4
AT+CIPMUX=0time out
AT+CIPMUX=0
AT+CIPMUX=0busy p...OKcmd=5
AT+CIPSTART="TCP","112.125.89.8",42137time out
AT+CIPSTART="TCP","112.125.89.8",42137
AT+CIPSTART="TCP","112.125.89.8",42137busy p...CONNECTOKcmd=6
AT+CIPSEND=7time out
AT+CIPSEND=7
AT+CIPSEND=7busy p...OK
> Recv 7 bytesSEND OKAT+CIPSEND=8OK
> Recv 8 bytesSEND OK+IPD,7:hello+IPD,8:yes okReceived data: hello+IPD,8:yes ok

然后我们去网站上发送

在串口助手上可以看见成功接收了

十一.完整源码

esp8266.c

#include "esp8266.h"
#include "tim.h"
#include "gpio.h"
#include "usart.h"
#include "stdio.h"
#include "string.h"// 定义ESP8266相关的缓冲区、长度、时间、标志位和等待响应字符串
uint8_t esp8266_buffer[128],esp8266_buff[1],esp8266_len=0,esp8266_time=0,esp8266_flag=0;
char esp8266_wait[100];// 定义ESP8266连接的WiFi信息和TCP服务器信息
const char ESP8266_WIFI_SSID[]="lty2";
const char ESP8266_WIFI_PassWord[]="2395832518";
const char ESP8266_WIFI_TCP_IP[]="112.125.89.8";
const char ESP8266_WIFI_TCP_PORT[]="42137";// 初始化ESP8266模块,启动定时器中断和UART接收中断
void ESP8266_Init(void)
{HAL_TIM_Base_Start_IT(ESP8266_TIM);HAL_UART_Receive_IT(ESP8266_UART,(uint8_t *)esp8266_buff,1);
}// 发送ESP8266命令,根据不同的命令编号和数据长度构造命令
void ESP8266_CMD(uint8_t cmd,uint16_t leng)
{char buffer[100];switch(cmd){case 0:sprintf(buffer,"AT+RST\r\n");sprintf(esp8266_wait,"OK");   break;case 1:sprintf(buffer,"AT\r\n");sprintf(esp8266_wait,"OK");break;	case 2:sprintf(buffer,"AT+CWMODE=1\r\n");sprintf(esp8266_wait,"OK");break;	case 3:sprintf(buffer,"AT+CWJAP=\"%s\",\"%s\"\r\n",ESP8266_WIFI_SSID,ESP8266_WIFI_PassWord);sprintf(esp8266_wait,"WIFI GOT IP");break;	case 4:sprintf(buffer,"AT+CWJAP?\r\n");sprintf(esp8266_wait,"OK");break;	case 5:sprintf(buffer,"AT+CIPMUX=0\r\n");sprintf(esp8266_wait,"OK");break;    case 6:sprintf(buffer,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",ESP8266_WIFI_TCP_IP,ESP8266_WIFI_TCP_PORT);sprintf(esp8266_wait,"OK");break;    case 7:sprintf(buffer,"AT+CIPSEND=%d\r\n",leng);sprintf(esp8266_wait,"");break;    case 8:sprintf(buffer,"");sprintf(esp8266_wait,"SEND OK");break;}ESP8266_commom(buffer);
}// 通用的ESP8266命令发送函数,发送命令并等待响应,超时会重新发送
void ESP8266_commom(const char *cmd)
{HAL_UART_Transmit(ESP8266_UART,(uint8_t *)cmd,strlen(cmd),100);esp8266_flag=0;while (esp8266_flag==0){if (esp8266_time>200){HAL_UART_Transmit(ESP8266_UART,(uint8_t *)cmd,strlen(cmd),100);printf("%s time out\r\n",cmd);esp8266_time=0;}}
}// 连接ESP8266到TCP服务器,依次发送多个初始化命令
void ESP8266_CONNECT_TO_TCP()
{for(uint8_t i = 0; i < 7; i++){  ESP8266_CMD(i,0);printf("cmd=%d\r\n",i);HAL_Delay(500);}
}// 通过ESP8266向TCP服务器发送数据
void ESP8266_send_TCP(const char *data)
{ESP8266_CMD(7,strlen(data));HAL_UART_Transmit(ESP8266_UART,(uint8_t *)data,strlen(data),100);ESP8266_CMD(8,0);
}// 检查字符串中是否包含指定子字符串
int contains_OK(const char *str, const char *substr) {if (strstr(str, substr) != NULL) {return 1; // 包含指定子字符串}return 0; // 不包含指定子字符串
}// 处理ESP8266接收的数据,检查是否有期望响应并调用IPD处理函数
void ESP8266_Change()
{printf("%s\r\n",esp8266_buffer);if(contains_OK(esp8266_buffer,esp8266_wait)){esp8266_flag=1;}ESP8266_IPD(esp8266_buffer);
}// 解析ESP8266接收到的IPD数据
void ESP8266_IPD(const char *data)
{char *p=data;uint8_t leng=0;char hand[256];if(strlen(data)>6)//printf("data[0]=%c,data[1]=%c,data[2]=%c,data[3]=%c,data[4]=%c\r\n",data[0],data[1],data[2],data[3],data[4]);if (data[2] == '+' && data[3] == 'I' && data[4] == 'P' && data[5] == 'D'){p+=6; while (*p != ':') {leng = leng * 10 + *p - '0';p++;	}p++; strncpy(hand, p, leng); hand[leng] = '\0'; printf("Received data: %s\r\n", hand);}
}// 处理ESP8266 UART接收中断,将接收到的数据存入缓冲区
void ESP8266_UART_Handler(void)
{esp8266_buffer[esp8266_len++]=esp8266_buff[0];esp8266_time=0;HAL_UART_Receive_IT(ESP8266_UART,(uint8_t *)esp8266_buff,1);
}// 处理ESP8266定时器中断,超时后处理接收的数据并清空缓冲区
void ESP8266_Time(void)
{esp8266_time++;if((esp8266_time>10)&&(esp8266_len>0)){esp8266_buffer[esp8266_len]=0;ESP8266_Change();memset(esp8266_buffer, '\0', sizeof(esp8266_buffer));esp8266_len=0;esp8266_time=0; } 
}// UART接收完成回调函数,当USART2接收完成时调用ESP8266 UART处理函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART2)		{	 ESP8266_UART_Handler();}			
}// 定时器周期溢出回调函数,当TIM2溢出时调用ESP8266时间处理函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM2){ESP8266_Time();}
}

esp8266.h

#ifndef HC_TR_H
#define HC_TR_H#include "main.h"#define ESP8266_UART    &huart2
#define ESP8266_TIM    &htim2
void ESP8266_Change();
void ESP8266_Time(void);
void ESP8266_Init(void);
void ESP8266_UART_Handler(void);
void ESP8266_CMD(uint8_t cmd,uint16_t leng);
int contains_OK(const char *str, const char *substr);
void ESP8266_commom(const char *cmd);
void ESP8266_CONNECT_TO_TCP();
void ESP8266_send_TCP(const char *data);
void ESP8266_IPD(const char *data);#endif 

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

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

相关文章

欧盟RED网络安全标准EN 18031-2的要求

欧盟RED网络安全标准EN 18031-2的要求 欧盟RED网络安全标准EN 18031-2的要求 ​ 适用产品范围&#xff1a; 能够处理个人隐私数据的可联网无线电设备。 不具备联网能力的三类无线电设备&#xff1a;玩具、儿童护理类设备、可穿戴类设备。 主要测试与评估内容&#xff1a; EN…

一起了解--CAST函数

CAST函数在SQL中用途广泛&#xff0c;不仅可以转换为数值类型&#xff0c;还可以在多种场景下用于数据类型转换。以下是一些常见的用途和示例&#xff1a; 类型转换 使用CAST函数可以在查询数据库时根据需要调整数据格式或类型 CAST(expression AS target_type) expression …

(50)课71:查看指定 query_id 的 SQL 语句的执行各个阶段的耗时情况 show profile for query query_id;

&#xff08;137&#xff09;查看指定 query_id 的 SQL 语句的执行各个阶段的耗时情况 show profile for query query_id &#xff1a; &#xff08;138&#xff09; 谢谢

AWS中国云的定时任务(AWS EventBridge+AWS Lambda)

问题 最近有一个每天在凌程定时同步数据给第三方系统的需求。需要使用AWS EventBridge和AWS Lambda结合的方式来同步数据给第三方系统。 思路 使用Python的ORM框架(例如&#xff1a;SQLAlchemy)查询到需要同步的数据&#xff0c;然后&#xff0c;使用http客户端&#xff08;…

开源PSS解析器

本章介绍开源PSS解析工具&#xff1a; 1. PSSTools语法解析器&#xff0c;这个工具仅包含一个语法解析器。 2. gen-pss&#xff0c;实现了语法解析器&#xff0c;和简单的Test realization&#xff0c;没有约束求解器。 本文将改造并使用gen-pss来生成C测试用例&#xff0…

《linux2.4 内存管理》:第 2 章 描述物理内存

Linux 适用于多种体系结构&#xff0c;需用体系结构无关方式描述内存。本章介绍影响 VM 行为的内存簇、页面和标志位结构。 非一致内存访问&#xff08;NUMA&#xff09;&#xff1a;在 VM 中&#xff0c;大型机器内存分簇&#xff0c;依簇与处理器距离&#xff0c;访问代价不…

数据湖是什么?数据湖和数据仓库的区别是什么?

目录 一、数据湖是什么 &#xff08;一&#xff09;数据湖的定义 &#xff08;二&#xff09;数据湖的特点 二、数据仓库是什么 &#xff08;一&#xff09;数据仓库的定义 &#xff08;二&#xff09;数据仓库的特点 三、数据湖和数据仓库的区别 &#xff08;一&#…

Smart Form Adobe form

强制更改内表:TNAPR se16-> Smart Form总览 Smart form 变量格式说明: &symbol& (括号中,小写字母为变量) &symbol& 屏蔽从第一位开始的N位 &symbol (n)& 只显示前N位 &symbol (S)& 忽略正负号 &symbol (<)& 符号在…

Linux 内核学习(11) --- Linux 链表结构

文章目录 Linked List 简介Linked List 操作方法链表头结点初始化创建链表节点添加节点到链表中从链表中删除节点从链表中替换节点移动链表中的节点检查链表链表遍历demo 实例 Linked List 简介 链表是一种数据结构&#xff0c;由一系列节点组成&#xff0c;每个节点包含数据部…

一分钟部署nginx-公网IP访问内网

前言 服务器内网下有nacos cluster&#xff08;3个节点&#xff09;&#xff0c;开放到公网并指定公司网络访问需要配置三次IP白名单&#xff0c;因此需要简化流程&#xff0c;通过nginx反向代理只配置1次IP白名单。 现在通过docker容器模拟环境&#xff0c;准备1台云服务器。…

C 语言分支与循环

目录 一. 分支结构&#xff1a;if 语句与 switch 语句 1. if 语句 2. switch 语句 二、关系操作符、条件操作符与逻辑操作符 1. 关系操作符 2. 条件操作符 3. 逻辑操作符 三、循环结构&#xff1a;while 循环、for 循环与 do - while 循环 1. while 循环 2. for 循…

【一文看懂Spring Boot2.x升级Spring Boot3.x】springboot2.x升级springboot3.x

springboot2.x升级springboot3.x 背景升级jdk版本为17以上springboot版本修改javax包更新mybatis-plus升级swagger升级springdocspringdoc配置背景 当前项目是springboot2.5.9版本的springboot+mybatis-plus项目,需要升级到springboot3.5.0项目。 升级jdk版本为17以上 Spri…

阳台光伏防逆流电表革新者:安科瑞ADL200N-CT/D16-WF

——为家庭能源管理提供高精度、智能化解决方案 一、阳台光伏爆发的背景 在全球能源转型与碳中和目标的驱动下&#xff0c;阳台光伏正以革命性姿态重塑家庭能源消费模式。从欧洲的“微型发电站”到中国的“万亿蓝海”&#xff0c;这一创新技术不仅撬动了能源市场的结构性变革…

美团完整面经

面试岗位 面试的岗位 - 2025春季校招 【转正实习】软件服务工程师-后端方向&#xff08;成都 - 软硬件服务-SaaS事业部&#xff09; 一面&#xff08;业务初试 - 30min&#xff09; 问题 自我介绍 Java基础 HashMap底层用的数据结构是什么&#xff1f;是线程安全的吗&…

pysnmp 操作流程和模块交互关系的可视化总结

1. SNMP GET 操作序列图 #mermaid-svg-KALvv8WkHJTsNCeu {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-KALvv8WkHJTsNCeu .error-icon{fill:#552222;}#mermaid-svg-KALvv8WkHJTsNCeu .error-text{fill:#552222;str…

关于 /proc/net/tcp 与 /proc/$pid/net/tcp 的关系分析

关于 /proc/net/tcp 与 /proc/$pid/net/tcp 的关系分析 1. 基础概念 在 Linux 系统中&#xff0c;每个进程必定归属于一个且仅一个网络命名空间&#xff08;Network Namespace&#xff09;。这是 Linux 命名空间隔离机制的核心特性之一。 /proc/net/tcp 显示当前网络命名空间…

微信小程序 - 保存手机号等信息到通讯录

主要使用小程序 wx.addPhoneContact 这个api 一、界面 <view class"tab-item" bindtap"addToPhoneContacts">保存</view> 二、js 逻辑文件中 addToPhoneContacts() {wx.addPhoneContact({firstName: this.data.firstName, // 姓名mobilePh…

计算机视觉一些定义解析

1.GCT&#xff08;Gated Channel Transformation&#xff09; 定义 GCT&#xff08;Gated Channel Transformation&#xff09;是一种用于增强卷积神经网络特征提取能力的模块。它的核心思想是通过门控机制对特征图的通道进行动态调整&#xff0c;从而突出对任务更有帮助的特…

美团NoCode的Database 使用指南

系列文章目录 第一篇&#xff1a;美团NoCode设计网站的尝试经验分 第二篇&#xff1a;美团NoCode中的Dev Mode 使用指南 文章目录 系列文章目录Database 适用场景一、什么是 Database&#xff1f;二、准备流程1. 申请账号 三、使用流程1.申请资源的同时可搭建 NoCode 页面&…

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…