ESP32(4)TCP通信
本章重点讲解 lwIP 的 Socket接口如何配置 TCP客户端,并在此基础上实现收发功能。
TCP Client 连接流程
在实现 TCP 协议之前,用户需要按照以下步骤配置结构体 sockaddr_in 的成员变量,以便建立 TCPClient 连接:
①:配置 ESP32-S3 设备连接网络(必须的,因为 WiFi 是无线通信,所以需搭建通信桥梁)。
②:将 sin_family 设置为 AF_INET,表示使用 IPv4 网络协议。
③:设置 sin_port 为所需的端口号,例如 8080。
④:设置 sin_addr.s_addr 为远程 IP 地址。
⑤:调用函数 Socket 创建 Socket 连接。请注意,该函数的第二个参数指定连接类型。SOCK_STREAM 表示 TCP 连接,而 SOCK_DGRAM 表示 UDP 连接。
⑥:调用函数 connect 连接远程 IP 地址。
⑦:调用适当的收发函数来接收或发送数据。
通过遵循这些步骤,用户可成功地配置并建立TCPClient连接,以实现数据的发送和接收。
TCP-Client
/** SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD** SPDX-License-Identifier: CC0-1.0*/#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_chip_info.h"
#include "esp_eap_client.h"
#include "esp_smartconfig.h"
#include "esp_flash.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_mac.h"#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>static const char *TAG = "network";
void tcp_client_task(void *parm);//=============================================================smart config===============================================================
static EventGroupHandle_t s_wifi_event_group;static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;static void smartconfig_task(void * parm);static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {xTaskCreate(smartconfig_task, "smartconfig_task", 4096, NULL, 3, NULL);} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {esp_wifi_connect();xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {ESP_LOGI(TAG, "Scan done");} else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {ESP_LOGI(TAG, "Found channel");} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {ESP_LOGI(TAG, "Got SSID and password");smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;wifi_config_t wifi_config;uint8_t ssid[33] = { 0 };uint8_t password[65] = { 0 };uint8_t rvd_data[33] = { 0 };bzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));#ifdef CONFIG_SET_MAC_ADDRESS_OF_TARGET_APwifi_config.sta.bssid_set = evt->bssid_set;if (wifi_config.sta.bssid_set == true) {ESP_LOGI(TAG, "Set MAC address of target AP: "MACSTR" ", MAC2STR(evt->bssid));memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));}
#endifmemcpy(ssid, evt->ssid, sizeof(evt->ssid));memcpy(password, evt->password, sizeof(evt->password));ESP_LOGI(TAG, "SSID:%s", ssid);ESP_LOGI(TAG, "PASSWORD:%s", password);if (evt->type == SC_TYPE_ESPTOUCH_V2) {ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );ESP_LOGI(TAG, "RVD_DATA:");for (int i=0; i<33; i++) {printf("%02x ", rvd_data[i]);}printf("\n");}ESP_ERROR_CHECK( esp_wifi_disconnect() );ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );esp_wifi_connect();} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}static void initialise_wifi(void)
{ESP_ERROR_CHECK(esp_netif_init());s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_wifi_init(&cfg) );ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK( esp_wifi_start() );
}static void smartconfig_task(void * parm)
{EventBits_t uxBits;ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );while (1) {uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);if(uxBits & CONNECTED_BIT) {ESP_LOGI(TAG, "WiFi Connected to ap");}if(uxBits & ESPTOUCH_DONE_BIT) {ESP_LOGI(TAG, "smartconfig over");esp_smartconfig_stop();xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);vTaskDelete(NULL);}}
}
//======================================================tcp client=================================================================
#define CONFIG_EXAMPLE_IPV4 #if defined(CONFIG_EXAMPLE_IPV4)
#define HOST_IP_ADDR "192.168.4.178"
#elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
#define HOST_IP_ADDR ""
#endif#define PORT 8080static const char *payload = "Message from ESP32 ";void tcp_client_task(void *parm)
{char rx_buffer[128];char host_ip[] = HOST_IP_ADDR;int addr_family = 0;int ip_protocol = 0;while (1) {
#if defined(CONFIG_EXAMPLE_IPV4)struct sockaddr_in dest_addr;inet_pton(AF_INET, host_ip, &dest_addr.sin_addr);dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(PORT);addr_family = AF_INET;ip_protocol = IPPROTO_IP;
#elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)struct sockaddr_storage dest_addr = { 0 };ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr));
#endifint sock = socket(addr_family, SOCK_STREAM, ip_protocol);if (sock < 0) {ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);}ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));if (err != 0) {ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);}ESP_LOGI(TAG, "Successfully connected");while (1) {int err = send(sock, payload, strlen(payload), 0);if (err < 0) {ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);}int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);// Error occurred during receivingif (len < 0) {ESP_LOGE(TAG, "recv failed: errno %d", errno);}// Data receivedelse {rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a stringESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);ESP_LOGI(TAG, "%s", rx_buffer);}}if (sock != -1) {ESP_LOGE(TAG, "Shutting down socket and restarting...");shutdown(sock, 0);close(sock);}}
}//===================================================================================================================================void app_main(void)
{printf("Hello world!\n");/* Print chip information */esp_chip_info_t chip_info;uint32_t flash_size;esp_chip_info(&chip_info);printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",CONFIG_IDF_TARGET,chip_info.cores,(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",(chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");unsigned major_rev = chip_info.revision / 100;unsigned minor_rev = chip_info.revision % 100;printf("silicon revision v%d.%d, ", major_rev, minor_rev);if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {printf("Get flash size failed");return;}printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());// Initialize NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);//initinitialise_wifi();while(1) {vTaskDelay(1000);}
}
注意,当smart config成功以后我们才创建tcp_client_task,保证流程同步,否则tcp无法成功连接。
测试结果:

TCP-Server
/** SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD** SPDX-License-Identifier: CC0-1.0*/#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_chip_info.h"
#include "esp_eap_client.h"
#include "esp_smartconfig.h"
#include "esp_flash.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_mac.h"#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>static const char *TAG = "network";
void tcp_client_task(void *parm);//=============================================================smart config===============================================================
static EventGroupHandle_t s_wifi_event_group;static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;static void smartconfig_task(void * parm);static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {xTaskCreate(smartconfig_task, "smartconfig_task", 4096, NULL, 3, NULL);} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {esp_wifi_connect();xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {ESP_LOGI(TAG, "Scan done");} else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {ESP_LOGI(TAG, "Found channel");} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {ESP_LOGI(TAG, "Got SSID and password");smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;wifi_config_t wifi_config;uint8_t ssid[33] = { 0 };uint8_t password[65] = { 0 };uint8_t rvd_data[33] = { 0 };bzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));#ifdef CONFIG_SET_MAC_ADDRESS_OF_TARGET_APwifi_config.sta.bssid_set = evt->bssid_set;if (wifi_config.sta.bssid_set == true) {ESP_LOGI(TAG, "Set MAC address of target AP: "MACSTR" ", MAC2STR(evt->bssid));memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));}
#endifmemcpy(ssid, evt->ssid, sizeof(evt->ssid));memcpy(password, evt->password, sizeof(evt->password));ESP_LOGI(TAG, "SSID:%s", ssid);ESP_LOGI(TAG, "PASSWORD:%s", password);if (evt->type == SC_TYPE_ESPTOUCH_V2) {ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );ESP_LOGI(TAG, "RVD_DATA:");for (int i=0; i<33; i++) {printf("%02x ", rvd_data[i]);}printf("\n");}ESP_ERROR_CHECK( esp_wifi_disconnect() );ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );esp_wifi_connect();} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}static void initialise_wifi(void)
{ESP_ERROR_CHECK(esp_netif_init());s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_wifi_init(&cfg) );ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK( esp_wifi_start() );
}static void smartconfig_task(void * parm)
{EventBits_t uxBits;ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );while (1) {uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);if(uxBits & CONNECTED_BIT) {ESP_LOGI(TAG, "WiFi Connected to ap");}if(uxBits & ESPTOUCH_DONE_BIT) {ESP_LOGI(TAG, "smartconfig over");esp_smartconfig_stop();vTaskDelete(NULL);}}
}
//======================================================tcp server=================================================================
#define CONFIG_EXAMPLE_IPV4#define PORT 8080
#define KEEPALIVE_IDLE 300
#define KEEPALIVE_INTERVAL 30
#define KEEPALIVE_COUNT 3static void do_retransmit(const int sock)
{int len;char rx_buffer[128];do {len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);if (len < 0) {ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);} else if (len == 0) {ESP_LOGW(TAG, "Connection closed");} else {rx_buffer[len] = 0; // Null-terminate whatever is received and treat it like a stringESP_LOGI(TAG, "Received %d bytes: %s", len, rx_buffer);// send() can return less bytes than supplied length.// Walk-around for robust implementation.int to_write = len;while (to_write > 0) {int written = send(sock, rx_buffer + (len - to_write), to_write, 0);if (written < 0) {ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);// Failed to retransmit, giving upreturn;}to_write -= written;}}} while (len > 0);
}static void tcp_server_task(void *pvParameters)
{char addr_str[128];int addr_family = (int)pvParameters;int ip_protocol = 0;int keepAlive = 1;int keepIdle = KEEPALIVE_IDLE;int keepInterval = KEEPALIVE_INTERVAL;int keepCount = KEEPALIVE_COUNT;struct sockaddr_storage dest_addr;#ifdef CONFIG_EXAMPLE_IPV4if (addr_family == AF_INET) {struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);dest_addr_ip4->sin_family = AF_INET;dest_addr_ip4->sin_port = htons(PORT);ip_protocol = IPPROTO_IP;}
#endif
#ifdef CONFIG_EXAMPLE_IPV6if (addr_family == AF_INET6) {struct sockaddr_in6 *dest_addr_ip6 = (struct sockaddr_in6 *)&dest_addr;bzero(&dest_addr_ip6->sin6_addr.un, sizeof(dest_addr_ip6->sin6_addr.un));dest_addr_ip6->sin6_family = AF_INET6;dest_addr_ip6->sin6_port = htons(PORT);ip_protocol = IPPROTO_IPV6;}
#endifint listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);if (listen_sock < 0) {ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);vTaskDelete(NULL);return;}int opt = 1;setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6)// Note that by default IPV6 binds to both protocols, it is must be disabled// if both protocols used at the same time (used in CI)setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
#endifESP_LOGI(TAG, "Socket created");int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));if (err != 0) {ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);ESP_LOGE(TAG, "IPPROTO: %d", addr_family);goto CLEAN_UP;}ESP_LOGI(TAG, "Socket bound, port %d", PORT);err = listen(listen_sock, 1);if (err != 0) {ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);goto CLEAN_UP;}while (1) {ESP_LOGI(TAG, "Socket listening");struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6socklen_t addr_len = sizeof(source_addr);int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);if (sock < 0) {ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);break;}// Set tcp keepalive optionsetsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));// Convert ip address to string
#ifdef CONFIG_EXAMPLE_IPV4if (source_addr.ss_family == PF_INET) {inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);}
#endif
#ifdef CONFIG_EXAMPLE_IPV6if (source_addr.ss_family == PF_INET6) {inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);}
#endifESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);do_retransmit(sock);shutdown(sock, 0);close(sock);}CLEAN_UP:close(listen_sock);vTaskDelete(NULL);
}//===================================================================================================================================void app_main(void)
{printf("Hello world!\n");/* Print chip information */esp_chip_info_t chip_info;uint32_t flash_size;esp_chip_info(&chip_info);printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",CONFIG_IDF_TARGET,chip_info.cores,(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",(chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");unsigned major_rev = chip_info.revision / 100;unsigned minor_rev = chip_info.revision % 100;printf("silicon revision v%d.%d, ", major_rev, minor_rev);if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {printf("Get flash size failed");return;}printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());// Initialize NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);//initinitialise_wifi();#ifdef CONFIG_EXAMPLE_IPV4xTaskCreate(tcp_server_task, "tcp_server", 4096, (void*)AF_INET, 5, NULL);#endif#ifdef CONFIG_EXAMPLE_IPV6xTaskCreate(tcp_server_task, "tcp_server", 4096, (void*)AF_INET6, 5, NULL);#endifwhile(1) {vTaskDelay(1000);}
}
测试:测试类比client操作。
相关文章:
ESP32(4)TCP通信
本章重点讲解 lwIP 的 Socket接口如何配置 TCP客户端,并在此基础上实现收发功能。 TCP Client 连接流程 在实现 TCP 协议之前,用户需要按照以下步骤配置结构体 sockaddr_in 的成员变量,以便建立 TCPClient 连接: ①:…...
【从零开始学习计算机科学】软件测试(二)单元测试 与 集成测试
【从零开始学习计算机科学】软件测试(二)单元测试 与 集成测试 单元测试概述单元测试的内容单元测试的优点单元测试的停止准则单元测试的过程与文档管理单元测试的任务集成测试集成测试关注的问题模块分析集成测试与系统测试的区别集成测试与开发的关系集成测试的层次集成测试…...
数学建模:MATLAB循环神经网络
一、简述 1.循环神经网络 循环神经网络(RNN)是一种用于处理序列数据的神经网络。不同于传统的前馈神经网络,RNN在隐藏层中加入了自反馈连接,使得网络能够对序列中的每个元素执行相同的操作,同时保持一个“记忆”状态…...
EagleTrader为何重申重要数据前后2分钟禁止交易?
3月12日,美国公布了2月份的CPI数据。 美国2月未季调CPI年率录得2.8%,为去年11月来新低,低于市场预期的2.9%。 美国2月季调后CPI月率录得0.2%,为去年10月来新低,预期值为0.3%,前值为0.5%。 数据公布后&#…...
【Spring】声明式事务传播机制
1. 所有传播行为 REQUIRED(默认类型): 如果当前存在事务,则加入该事务;如果没有,则新建一个事务。适用于大多数业务场景。 SUPPORTS: 如果当前存在事务,则加入该事务;…...
个人blog系统 前后端分离 前端js后端go
系统设计: 1.使用语言:前端使用vue,并使用axios向后端发送数据。后端使用的是go的gin框架,并使用grom连接数据库实现数据存储读取。 2.设计结构: 最终展示:仅展示添加模块,其他模块基本相似 前…...
单元测试mock
一、背景 现在有A类,B类,C类,A类依赖B类,依赖C类,如果想要测试A类中的某个方法的业务逻辑。A类依赖其他类,则把其他类给mock,然后A类需要真实对象。这样就可以测试A类中的方法。 举例:Ticket类需要调用Flight类和Pas…...
OpenGL 将屏幕上的二维坐标转换为三维空间中的一个点
本文主要介绍将屏幕上的二维坐标转换为三维空间中的一个点,该点位于 近 平面上(即 Z 坐标为 -1)。 一、步骤概述 屏幕坐标到标准化设备坐标 (NDC): 将屏幕坐标 (x, y) 转换为 NDC 坐标系。NDC 到相机空间: 使用逆投影矩阵将 NDC 坐标转换到相…...
golang接口用法-代码案例
文章目录 Go语言中接口(interface)的含义接口的常见应用场景示例1示例2(Dog 和 Cat)使用场景-多数据库 Go语言中接口(interface)的含义 接口在Go语言中是一种类型,它定义了一组方法的集合。一个…...
ORA-12162: TNS:net service name is incorrectly specified
1.现象 SQL plus 连接实例报错,已确定实例是open状态。 [rootlocalhost ~]# su - oracle [oraclelocalhost ~]$ sqlplus / as sysdbaSQL*Plus: Release 19.0.0.0.0 - Production on Sat Mar 15 10:20:56 2025 Version 19.11.0.0.0Copyright (c) 1982, 2020, Orac…...
基于 Verilog 的时序设计:从理论到实践的深度探索
在数字电路设计领域,时序设计是一个至关重要的环节,它涉及到组合逻辑电路与时序逻辑电路的设计差异、时钟信号的运用以及触发器的工作原理等多个方面。本文将围绕基于 Verilog 的时序设计实验展开,详细阐述实验过程、代码实现以及结果分析,帮助读者深入理解时序设计的核心概…...
GreenKGC: A Lightweight Knowledge Graph Completion Method(论文笔记)
CCF等级:A 发布时间:2023年7月 代码位置 25年3月17日交 目录 一、简介 二、原理 1.整体 2.表示学习 3.特征修剪 4.决策学习 三、实验性能 1.主要结果 2.消融实验 四、结论和未来工作 一、简介 传统知识图谱补全方法中,嵌入维度…...
SSM基础专项复习5——Maven私服搭建(2)
系列文章 1、SSM基础专项复习1——SSM项目整合-CSDN博客 2、SSM基础专项复习2——Spring 框架(1)-CSDN博客 3、SSM基础专项复习3——Spring框架(2)-CSDN博客 4、SSM基础专项复习4——Maven项目管理工具(1ÿ…...
Linux中的epoll简单使用案例
I/O 多路复用允许一个进程或线程同时监控多个网络 sockets 的状态。它通过单个系统调用(select)来检查多个 sockets 是否有数据可读、可写或是否有异常。Linux 提供了多种 I/O 复用技术,包括上面提到的 select、以及 poll、epoll。 创建epol…...
ASP4644四通道降压稳压器的工业高效电源管理方案
ASP4644工业级型号(ASP4644I6B)是一款专为工业场景设计的四通道降压稳压器,支持-40C至85C工作温度。其核心特性包括: 宽输入电压范围:4V–14V,适配工业现场多变的电源环境。 高负载能力:单通道…...
kali破解Pdf/execl/word
一、准备工作 1.工具安装 Kali Linux 内置部分工具,需补充安装以下工具: sudo apt update sudo apt install pdfcrack hashcat john -y git clone https://github.com/magnumripper/JohnTheRipper # 更新版John 2.字典准备 常用字典:Kal…...
宇树科技纯技能要求总结
一、嵌入式开发与硬件设计 核心技能 嵌入式开发: 精通C/C,熟悉STM32、ARM开发熟悉Linux BSP开发及驱动框架(SPI/UART/USB/FLASH/Camera/GPS/LCD)掌握主流平台(英伟达、全志、瑞芯微等) 硬件设计:…...
RabbitMq C++客户端的使用
1.RabbitMq介绍 RabbitMQ 是一款开源的消息队列中间件,基于 AMQP(高级消息队列协议)实现,支持多种编程语言和平台。以下是其核心特点和介绍: 核心特点 多语言支持 提供 Java、Python、C#、Go、JavaScript 等语言的客…...
用通义大模型写爬虫程序,汇总各科成绩
需求:根据各科网址,输入学号、姓名查询成绩。 中间反反复复很多次,本文只记下重点的几次和大模型的沟通历史。 输入界面 查询界面 round0(最初的问题) 请在windows下,使用python的selenium库࿰…...
电商项目Ts版本
文章目录 项目地址一、环境安装1.1 配置作为导入1.2 文件目录 二、路由2.1 publicRoutes 项目地址 教程作者:教程地址: 代码仓库地址: 所用到的框架和插件: dbt airflow一、环境安装 1.1 配置作为导入 vite.config.ts impor…...
HarmonyOS Next中的弹出框使用
HarmonyOS Next弹出框概述及分类 弹出框是一种模态窗口,通常用于在保持当前上下文环境的同时,临时展示用户需关注的信息或待处理的操作。用户需在模态弹出框内完成相关交互任务之后,才能退出模态模式。弹出框可以不与任何组件绑定࿰…...
C++实现的数据结构示例,涵盖链表、数组、树和图
使用C实现的数据结构示例,涵盖链表、数组、树和图的基本操作: 链表(单向链表) #include <iostream> using namespace std;struct Node {int data;Node* next;Node(int val) : data(val), next(nullptr) {} };class Linked…...
FPGA中级项目4——DDS实现
FPGA中级项目4——DDS实现 DDS简介 DDS(直接数字频率合成器,Direct Digital Frequency Synthesis)是一种基于数字信号处理技术的频率合成方法,广泛应用于通信、雷达、仪器仪表等领域。在 FPGA中实现 DDS 具有灵活性高、集成度强、…...
深度学习-149-langchain之如何不使用with_structured_output()从模型中返回结构化数据
文章目录 1 不使用with_structured_output()方法1.1 问题背景1.2 输出解析器1.3 远程deepseek大模型API2 基于提示词2.1 直接使用提示词2.2 少样本提示词3 直接提示和解析模型输出3.1 使用PydanticOutputParser3.1.1 构建解析器3.1.2 构建提示模板3.1.3 调用大模型3.1.4 调用链…...
STM32 DAC详解:从原理到实战输出正弦波
目录 一、DAC基础原理1.1 DAC的作用与特性1.2 DAC功能框图解析 二、DAC配置步骤2.1 硬件配置2.2 初始化结构体详解 三、DAC数据输出与波形生成3.1 数据格式与电压计算3.2 正弦波生成实战3.2.1 生成正弦波数组3.2.2 配置DMA传输3.2.3 定时器触发配置 四、常见问题与优化建议4.1 …...
深度学习框架PyTorch——从入门到精通(5)构建神经网络
构建神经网络 获取训练设备定义类模型层nn.Flattennn.Linearnn.ReLUnn.Sequentialnn.Softmax 模型参数补充说明argmax 神经网络是由一些层或者模块组成的,这些层和模块会对数据进行各种操作。 在 PyTorch 里,torch.nn 这个命名空间提供了你搭建自己神经网…...
基于PyQt5与Open3D的轻量化BIM工具开发指南(下)
基于PyQt5与Open3D的轻量化BIM工具开发指南(下) ——参数化建模、数据导出与性能优化 【跳转】基于PyQt5与Open3D的轻量化BIM工具开发指南(上) 四、详细实现步骤(Part 2) 3. 参数化建模…...
Pytest项目_day01(HTTP接口)
HTTP HTTP是一个协议(服务器传输超文本到浏览器的传送协议),是基于TCP/IP通信协议来传输数据(HTML文件,图片文件,查询结果等)。 访问域名 例如www.baidu.com就是百度的域名,我们想…...
在vue项目中,使用Patch请求,实现根据id修改某张发票的日结状态
目录 前言 一.问题描述 二.后端实现 1.分析 2.检查后端拦截器,看看是否允许接收Patch类型的请求 3.编写Dto 4.编写controller层 5.编写service层 6.mapper层 7.使用apifox,测试后端接口的可用性 三.前端实现 1.封装api(本质是ax…...
Android Zygote的进程机制
目录 ✅ Android Zygote 进程机制详解 🚩 一、Zygote 的作用 ⚙️ 二、Zygote 启动流程 ✅ 1. init 进程启动 Zygote ✅ 2. Zygote 初始化虚拟机与核心类库 ✅ 3. Zygote 监听 Socket ✅ 4. Zygote fork 创建应用进程 🔥 三、Zygote 与应用进程之…...
