ESP32S3 WIFI 实现TCP服务器和静态IP

一、 TCP服务器代码

代码由station_example_main的官方例程修改

/* WiFi station ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <stdlib.h>
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/sockets.h"
#include <lwip/netdb.h>/* The examples use WiFi configuration that you can set via project configuration menuIf you'd rather not, just change the below entries to strings withthe config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID      CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS      CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY  CONFIG_ESP_MAXIMUM_RETRY#define EXAMPLE_MAX_STA_CONN        4  // 最大客户端连接数
#define PORT                        8080
#define KEEPALIVE_IDLE              5
#define KEEPALIVE_INTERVAL          5
#define KEEPALIVE_COUNT             3#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
#define EXAMPLE_H2E_IDENTIFIER ""
#elif CONFIG_ESP_WPA3_SAE_PWE_HASH_TO_ELEMENT
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#elif CONFIG_ESP_WPA3_SAE_PWE_BOTH
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#endif
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;/* The event group allows multiple bits for each event, but we only care about two events:* - we are connected to the AP with an IP* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1
#define WIFI_CONNECTED_SUCCESS      BIT2// 客户端任务参数结构体
typedef struct {int socket;struct sockaddr_in addr;
} client_params_t;static const char *TAG = "wifi station";static int s_retry_num = 0;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) {esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {esp_wifi_connect();s_retry_num++;ESP_LOGI(TAG, "retry to connect to the AP");} else {xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);}ESP_LOGI(TAG,"connect to the AP fail");} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));s_retry_num = 0;xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_SUCCESS |WIFI_CONNECTED_BIT);}
}void wifi_init_sta(void)
{s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));esp_event_handler_instance_t instance_any_id;esp_event_handler_instance_t instance_got_ip;ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&instance_any_id));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,&instance_got_ip));wifi_config_t wifi_config = {.sta = {.ssid = EXAMPLE_ESP_WIFI_SSID,.password = EXAMPLE_ESP_WIFI_PASS,/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (password len => 8).* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.*/.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,.sae_pwe_h2e = ESP_WIFI_SAE_MODE,.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );ESP_ERROR_CHECK(esp_wifi_start() );ESP_LOGI(TAG, "wifi_init_sta finished.");/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,pdFALSE,pdFALSE,portMAX_DELAY);/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually* happened. */if (bits & WIFI_CONNECTED_BIT) {ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else if (bits & WIFI_FAIL_BIT) {ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else {ESP_LOGE(TAG, "UNEXPECTED EVENT");}
}// 客户端处理任务
void client_task(void *pvParameters)
{client_params_t *params = (client_params_t *)pvParameters;int sock = params->socket;struct sockaddr_in addr = params->addr;free(pvParameters); // 释放分配的内存char addr_str[128];inet_ntoa_r(addr.sin_addr, addr_str, sizeof(addr_str) - 1);ESP_LOGI(TAG, "客户端任务启动: IP=%s, 端口=%d", addr_str, ntohs(addr.sin_port));char rx_buffer[128];char tx_buffer[128];// 设置keepalive选项int keepAlive = 1;int keepIdle = KEEPALIVE_IDLE;int keepInterval = KEEPALIVE_INTERVAL;int keepCount = KEEPALIVE_COUNT;setsockopt(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));// 设置接收超时struct timeval timeout;timeout.tv_sec = 10;timeout.tv_usec = 0;setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));// 处理客户端数据while (1) {int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);if (len < 0) {if (errno == EAGAIN || errno == EWOULDBLOCK) {// 超时,继续等待continue;}ESP_LOGE(TAG, "接收数据错误: errno %d", errno);break;} else if (len == 0) {ESP_LOGI(TAG, "客户端 %s 断开连接", addr_str);break;} else {rx_buffer[len] = 0; // 添加null终止符ESP_LOGI(TAG, "从 %s 收到 %d 字节: %s", addr_str, len, rx_buffer);// 发送响应int tx_len = snprintf(tx_buffer, sizeof(tx_buffer), " server has received %d bytes", len);int sent = send(sock, tx_buffer, tx_len, 0);if (sent < 0) {ESP_LOGE(TAG, "发送失败: errno %d", errno);break;}}}// 关闭socketshutdown(sock, 0);close(sock);ESP_LOGI(TAG, "客户端 %s 处理结束", addr_str);vTaskDelete(NULL);
}// TCP服务器任务
void tcp_server_task(void *pvParameters)
{char addr_str[128];int addr_family = AF_INET;int ip_protocol = IPPROTO_IP;struct sockaddr_in server_addr;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);// 创建socketint listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);if (listen_sock < 0) {ESP_LOGE(TAG, "无法创建socket: errno %d", errno);vTaskDelete(NULL);return;}// 设置socket选项 (允许地址重用)int opt = 1;setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));// 绑定socketint err = bind(listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));if (err != 0) {ESP_LOGE(TAG, "socket绑定失败: errno %d", errno);close(listen_sock);vTaskDelete(NULL);return;}// 开始监听err = listen(listen_sock, EXAMPLE_MAX_STA_CONN);if (err != 0) {ESP_LOGE(TAG, "socket监听失败: errno %d", errno);close(listen_sock);vTaskDelete(NULL);return;}ESP_LOGI(TAG, "TCP服务器已启动,监听端口: %d", PORT);while (1) {ESP_LOGI(TAG, "等待新的客户端连接...");struct sockaddr_in client_addr;socklen_t client_len = sizeof(client_addr);int client_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &client_len);if (client_sock < 0) {ESP_LOGE(TAG, "接受连接失败: errno %d", errno);continue;}// 将客户端IP转换为字符串inet_ntoa_r(client_addr.sin_addr, addr_str, sizeof(addr_str) - 1);ESP_LOGI(TAG, "新的客户端连接: IP=%s, 端口=%d", addr_str, ntohs(client_addr.sin_port));// 为客户端任务分配参数client_params_t *params = malloc(sizeof(client_params_t));if (params == NULL) {ESP_LOGE(TAG, "内存分配失败");close(client_sock);continue;}params->socket = client_sock;params->addr = client_addr;// 创建客户端任务if (xTaskCreate(client_task, "client_task", 4096, params, 5, NULL) != pdPASS) {ESP_LOGE(TAG, "无法创建客户端任务");free(params);close(client_sock);}}close(listen_sock);vTaskDelete(NULL);
}
void app_main(void)
{//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);ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");wifi_init_sta();xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_SUCCESS, pdFALSE, pdFALSE, portMAX_DELAY);vTaskDelay(1000 / portTICK_PERIOD_MS);// 创建TCP服务器任务xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL);
}

运行测试

I (1616) esp_netif_handlers: sta ip: 192.168.137.54, mask: 255.255.255.0, gw: 192.168.137.1
I (1616) wifi station: got ip:192.168.137.54
I (1616) wifi station: connected to ap SSID:zhaozhong password:12345678
I (2616) wifi station: TCP服务器已启动,监听端口: 8080
I (2616) wifi station: 等待新的客户端连接...
I (2616) main_task: Returned from app_main()
I (18386) wifi station: 新的客户端连接: IP=192.168.137.1, 端口=59883
I (18386) wifi station: 等待新的客户端连接...
I (18386) wifi station: 客户端任务启动: IP=192.168.137.1, 端口=59883
I (19296) wifi:<ba-add>idx:0 (ifx:0, d6:54:8b:b2:90:f3), tid:0, ssn:7, winSize:64
I (23296) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (28216) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (29146) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (58626) wifi station: 新的客户端连接: IP=192.168.137.230, 端口=49416
I (58626) wifi station: 等待新的客户端连接...
I (58626) wifi station: 客户端任务启动: IP=192.168.137.230, 端口=49416
I (58626) wifi station: 新的客户端连接: IP=192.168.137.230, 端口=49416
I (58626) wifi station: 等待新的客户端连接...
I (58626) wifi station: 客户端任务启动: IP=192.168.137.230, 端口=49416
I (78916) wifi station:192.168.137.230 收到 10 字节: 5588888811
I (87206) wifi station:192.168.137.230 收到 5 字节: hello
I (93646) wifi station:192.168.137.230 收到 5 字节: hello
I (98886) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (101326) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (106256) wifi station: 客户端 192.168.137.1 断开连接
  1. ESP32连接电脑创建的热点,并分配到了192.168.137.54地址。手机分配到了230地址
    在这里插入图片描述
  2. ESP32启动TCP服务器,然后用电脑网络助手和手机的网络助手连接。然后发送数据测试。
    在这里插入图片描述
  3. 可以实现多连接等功能。

二、 ESP32设置为静态IP

增加部分代码设置静态IP,然后在WiFi启动之前调用即可

// 静态IP配置
#define EXAMPLE_ESP_STATIC_IP      "192.168.137.100"
#define EXAMPLE_ESP_STATIC_GW      "192.168.137.1"
#define EXAMPLE_ESP_STATIC_NM      "255.255.255.0"// 设置静态IP的函数
void set_static_ip()
{esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");if (netif == NULL) {ESP_LOGE(TAG, "获取网络接口失败");return;}// 设置静态IP配置esp_netif_ip_info_t ip_info;memset(&ip_info, 0, sizeof(esp_netif_ip_info_t));ip_info.ip.addr = ipaddr_addr(EXAMPLE_ESP_STATIC_IP);ip_info.gw.addr = ipaddr_addr(EXAMPLE_ESP_STATIC_GW);ip_info.netmask.addr = ipaddr_addr(EXAMPLE_ESP_STATIC_NM);// 应用静态IP配置esp_netif_dhcpc_stop(netif);esp_netif_set_ip_info(netif, &ip_info);ESP_LOGI(TAG, "静态IP设置成功 (使用esp_netif)");
}void wifi_init_sta(void)
{s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));esp_event_handler_instance_t instance_any_id;esp_event_handler_instance_t instance_got_ip;ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&instance_any_id));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,&instance_got_ip));wifi_config_t wifi_config = {.sta = {.ssid = EXAMPLE_ESP_WIFI_SSID,.password = EXAMPLE_ESP_WIFI_PASS,/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (password len => 8).* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.*/.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,.sae_pwe_h2e = ESP_WIFI_SAE_MODE,.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );// 在启动WiFi前设置静态IPset_static_ip();ESP_ERROR_CHECK(esp_wifi_start() );ESP_LOGI(TAG, "wifi_init_sta finished.");/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,pdFALSE,pdFALSE,portMAX_DELAY);/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually* happened. */if (bits & WIFI_CONNECTED_BIT) {ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else if (bits & WIFI_FAIL_BIT) {ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else {ESP_LOGE(TAG, "UNEXPECTED EVENT");}
}

进行测试

I (567) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
I (577) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
I (587) esp_netif_handlers: sta ip: 192.168.137.100, mask: 255.255.255.0, gw: 192.168.137.1
I (597) wifi station: got ip:192.168.137.100
I (597) wifi station: connected to ap SSID:zhaozhong password:12345678
I (647) wifi:AP's beacon interval = 102400 us, DTIM period = 3
I (1607) wifi station: TCP服务器已启动,监听端口: 8080
I (1607) wifi station: 等待新的客户端连接...
I (1607) main_task: Returned from app_main()
I (8847) wifi station: 新的客户端连接: IP=192.168.137.1, 端口=54251
I (8847) wifi station: 等待新的客户端连接...
I (8847) wifi station: 客户端任务启动: IP=192.168.137.1, 端口=54251
I (11307) wifi:<ba-add>idx:0 (ifx:0, d6:54:8b:b2:90:f3), tid:0, ssn:6, winSize:64
I (13447) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (14987) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (15907) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (21127) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn
I (21437) wifi station:192.168.137.1 收到 20 字节: http://www.cmsoft.cn

IP已经固定为192.168.137.100 静态IP设置正常。

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

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

相关文章

物质与空:边界中的确定性,虚无中的无限可能——跨学科视角下的存在本质探析

一、哲学框架&#xff1a;二元性与超越性 1. 物质的边界性&#xff1a;有限世界的确定性法则 在人类认知的起点&#xff0c;物质以"非0即1"的绝对姿态显现。一块石头、一滴水、乃至微观粒子&#xff0c;都以明确的边界定义自身存在。这种确定性映射着&#xff1a; 亚…

linux常用指令(10)

那么我们就继续来学习linux指令的使用,来了解搜索查找类的相关指令,话不多说,来看. 搜索查找类 1.find指令 find将从指定目录向下遍历其各个子目录,将满足条件的条件或目录显示在终端 基本语法 find[搜索范围][项项] 选项说明 -name<查询方式> 按照指定的文件名查找…

AWTK-WEB 快速入门(6) - JS WebSocket 应用程序

WebSocket 可以实现双向通信&#xff0c;适合实时通信场景。本文介绍一下使用 Javacript 语言开发 AWTK-WEB 应用程序&#xff0c;并用 WebSocket 与服务器通讯。 用 AWTK Designer 新建一个应用程序 先安装 AWTK Designer&#xff1a; https://awtk.zlg.cn/web/index.html …

机器学习——集成学习框架(GBDT、XGBoost、LightGBM、CatBoost)、调参方法

一、集成学习框架 对训练样本较少的结构化数据领域&#xff0c;Boosting算法仍然是常用项 XGBoost、CatBoost和LightGBM都是以决策树为基础的集成学习框架 三个学习框架的发展是&#xff1a;XGBoost是在GBDT的基础上优化而来&#xff0c;CatBoost和LightGBM是在XGBoost的基础上…

Leetcode 最长递增子序列的个数

java solution class Solution {public int findNumberOfLIS(int[] nums) {//边界情况处理int n nums.length;if(n < 1) return n;//然后我们创建2个数组, 分别是count数组和length数组,//length[i]的含义是以i结尾的子数组的最长递增子序列长度//count[i]的含义是以i结尾…

原型验证后客户推翻原有需求,如何止损

原型验证后客户推翻原有需求时止损的有效方法包括&#xff1a;迅速评估影响范围、立即开展沟通确认、调整项目计划和资源配置、更新变更管理流程、协商成本分担机制。其中&#xff0c;迅速评估影响范围是关键&#xff0c;项目团队必须立即明确此次变更的具体影响&#xff0c;包…

在rockylinux9.4安装mongodb报错:缺少:libcrypto.so.10文件库

问题点&#xff1a; rockylinux9.4系统环境报错&#xff1a; ./mongod: error while loading shared libraries: libcrypto.so.10: cannot open shared object file: No such file or directory 解决方法&#xff1a; Ps&#xff1a;解压之后&#xff0c;检查mongodb的依赖环境…

如何应对竞品分析不足导致的方案偏差

应对竞品分析不足导致方案偏差的有效措施包括&#xff1a;深入竞品调研、建立定期竞品分析机制、明确竞品分析维度、引入专业竞品分析工具、优化内部沟通反馈机制。其中&#xff0c;深入竞品调研尤为重要。通过全面深入地分析竞争对手的产品策略、市场定位及用户反馈&#xff0…

基于Python+LanceDB实战向量搜索

本篇实战演示向量搜索的实现和示例。 预期效果 给出一个查询的字符串&#xff0c;通过向量搜索&#xff0c;在下面三个语句中搜索出关联性最大的那句。 "熊猫是中国的国宝&#xff0c;主要栖息在四川山区。","长城是古代中国建造的军事防御工事&#xff0c;全…

在 Linux(Ubuntu / CentOS 7)上快速搭建我的世界 MineCraft 服务器,并实现远程联机,详细教程

Linux 部署 MineCraft 服务器 详细教程&#xff08;丐版&#xff0c;无需云服务器&#xff09; 一、虚拟机 Ubuntu 部署二、下载 Minecraft 服务端三、安装 JRE 21四、安装 MCS manager 面板五、搭建服务器六、本地测试连接七、下载樱花&#xff0c;实现内网穿透&#xff0c;邀…

【科研绘图系列】R语言绘制重点物种进化树图(taxa phylogenetic tree)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图输出图片系统信息介绍 【科研绘图系列】R语言绘制重点物种进化树图(taxa phylogenetic tree) 加载R包 library(tidyverse) library(ape…

浏览器渲染过程

浏览器的渲染过程是多个线程、进程和阶段的复杂编排&#xff0c;它将原始的 HTML、CSS 和 JavaScript 转换为屏幕上的交互像素。 你在浏览器中输入一个 URL 并按下回车键 网站在你的屏幕上呈现出来 注意&#xff1a;本文中&#xff0c;将使用 “客户端&#xff08;client&am…

华鲲振宇天工TG225 B1国产服务器试装openEuler22.03 -SP4系统

今天测试了一下在华鲲振宇公司的天工TG225 B1国产服务器上进行openEuler22.03 -SP4操作系统的试装&#xff0c;本文记录整个测试过程。 一、服务器信息 1、服务器型号 Huakun TG225 B1 (D) 2、登录IPMI帐户信息 初始用户名Tech.ON 密码TianGong8000 二、磁盘RAID配置 测试…

Qemu-STM32(十二):STM32F103 框架代码添加

简介 本系列博客主要描述了STMF103的qemu模拟器实现&#xff0c;进行该项目的原因有两点: 作者在高铁上&#xff0c;想在STM32F103上验证一个软件框架时&#xff0c;如果此时掏出开发板&#xff0c;然后接一堆的线&#xff0c;旁边的人估计会投来异样的目光&#xff0c;特别是…

英伟达与通用汽车深化合作,澳特证券am broker助力科技投资

在近期的GTC大会上&#xff0c;英伟达CEO黄仁勋宣布英伟达将与通用汽车深化合作&#xff0c;共同推进AI技术在自动驾驶和智能工厂的应用。此次合作标志着自动驾驶汽车时代的加速到来&#xff0c;同时也展示了英伟达在AI技术领域的最新进展。      合作内容包括&#xff1a;…

将 Markdown 表格结构转换为Excel 文件

在数据管理和文档编写过程中&#xff0c;我们经常使用 Markdown 来记录表格数据。然而&#xff0c;Markdown 格式的表格在实际应用中不如 Excel 方便&#xff0c;特别是需要进一步处理数据时。因此&#xff0c;我们开发了一个使用 wxPython 的 GUI 工具&#xff0c;将 Markdown…

HarmonyOS NEXT 关于鸿蒙的一多开发(一次开发,多端部署) 1+8+N

官方定义 定义&#xff1a;一套代码工程&#xff0c;一次开发上架&#xff0c;多端按需部署。 目标&#xff1a;支撑开发者快速高效的开发支持多种终端设备形态的应用&#xff0c;实现对不同设备兼容的同时&#xff0c;提供跨设备的流转、迁移和协同的分布式体验。 什么是18…

Nacos

简介 Nacos&#xff08;Dynamic Naming and Configuration Service&#xff09;是阿里巴巴开源的一款动态服务发现、配置管理和服务管理平台&#xff0c;旨在为微服务架构提供高可用、高性能的解决方案。其核心功能包括服务注册与发现、动态配置管理、服务健康监测、动态 DNS …

Win11系统下qq远程不能控制对方电脑(鼠标点不动)的解决方法

在被控制的电脑上&#xff0c;打开控制面板&#xff0c;点击系统和安全 点击更改用户账户控制设置 下拉用户控制设置至最低&#xff0c;从不通知&#xff0c;点击确定 返回控制面板系统与安全&#xff0c;带年纪允许远程访问 点击允许远程协助连接这台计算机 重启电脑 再次打…

猎豹移动营收连续三季增长,AI驱动的猎豹成绩单怎么分析?

3月26日&#xff0c;猎豹移动发布2024年Q4及全年财报&#xff0c;这份财报我们到底该该怎么分析呢&#xff1f; 首先&#xff0c;整体财务表现稳健&#xff0c;营收连续三季增长。从财务数据来看&#xff0c;猎豹移动整体表现稳健。2024年Q4及全年财报显示&#xff0c;总收入达…