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
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84671.shtml
英文地址,請注明出處:http://en.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架構與數據庫之間的關系,以…