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

news2025/3/31 20:06:03

一、 TCP服务器代码

代码由station_example_main的官方例程修改

/* WiFi station Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS 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 menu

   If you'd rather not, just change the below entries to strings with
   the 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;
            }
        }
    }
    
    // 关闭socket
    shutdown(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);
    
    // 创建socket
    int 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));
    
    // 绑定socket
    int 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 NVS
    esp_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前设置静态IP
    set_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.coloradmin.cn/o/2323638.html

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

相关文章

docker中安装 python

ubuntu 1、安装源码编译所需依赖 apt-get install -y gcc g make cmake libsqlite3-dev zlib1g-dev libssl-dev libffi-dev 2、下载python安装包 python-release安装包下载_开源镜像站-阿里云 3、解压安装 tar -zxvf Python-3.7.5.tgz cd Python-3.7.5 ./configure --prefix…

数据库----单表、多表

数据库 create database 数据库名称;---创建数据库create database 数据库名称 default charsetutf8mb4;---创建数据库&#xff0c;同时指定编码show databases;---查看当前数据库管理下存在多少数据库show databases like "db_%";---查询以db_开头的数据库select d…

ubuntu 22.04 一键安装 lxd

LXD系列 LXD是一个现代、安全且功能强大的系统容器和虚拟机管理器。 它为在容器或虚拟机中运行和管理完整的 Linux 系统提供了统一的体验。LXD 支持大量 Linux 发行版的映像(官方 Ubuntu 映像和社区提供的映像),并且围绕

HO与OH差异之Navigation三

在上一篇内容中我们介绍了HO与OH差异之Navigator&#xff0c;我们也了解了Navigator的基本概念和大致了解了一下他的基础用法&#xff0c;既然谈到差异肯定就不止这两种差异&#xff0c;今天就让我们来了解第三种差异NavRouter&#xff0c;其中在HO中我们并没有这种路由方式但是…

模型压缩与迁移:基于蒸馏技术的实战教程

1.前言 模型蒸馏&#xff08;Model Distillation&#xff09;&#xff0c;又称为知识蒸馏&#xff08;Knowledge Distillation&#xff09;&#xff0c;是一种将大型、复杂的模型&#xff08;通常称为教师模型&#xff0c;Teacher Model&#xff09;的知识转移到小型、简单模型…

XSS通关技巧

目录 第一关&#xff1a; 第二关&#xff1a; 第三关&#xff1a; 第四关&#xff1a; 第五关&#xff1a; 第六关&#xff1a; 第七关&#xff1a; 第八关&#xff1a; 第九关&#xff1a; 第十关&#xff1a; 第十一关&#xff1a; 第十二关&#xff1a; 第十三关&#xff1a…

el-tree树多选,将选中的树对象中某个字段值改为true,并过滤出所有为true的对象,组成新的数组

功能实现&#xff1a; el-tree树多选&#xff0c;将选中的树对象中某个字段值改为true,并过滤出所有为true的对象&#xff0c;组成新的数组提交给后端 <template><div><!-- 树形菜单 --><el-tree:data"stageList"show-checkboxdefault-expand-…

大文件版本管理git-lfs

1. 安装 Git Large File Storage (LFS) 是一个 开源的 Git 扩展&#xff0c;用于替换 Git 仓库中的大文件&#xff0c;用指针文件替代实际的大文件&#xff0c;可以在保持仓库轻量级的同时&#xff0c;有效地管理大型文件。 如果install提示失败&#xff0c;多试几次&#xf…

融合YOLO11与行为树的人机协作智能框架:动态工效学优化与自适应安全决策

人工智能技术要真正发挥其价值&#xff0c;必须与生产生活深度融合&#xff0c;为产业发展和人类生活带来实际效益。近年来&#xff0c;基于深度学习的机器视觉技术在工业自动化领域取得了显著进展&#xff0c;其中YOLO&#xff08;You Only Look Once&#xff09;算法作为一种…

Postgresql源码(142)子查询提升pull_up_sublinks

1 案例 drop table t_fun01; create table t_fun01 (image_id numeric primary key, content_id varchar(50), file_code varchar(20)); create index idx3 on t_fun01(content_id); create index idx4 on t_fun01(file_code); insert into t_fun01 select t.i, t.i%10, t.i%1…

23种设计模式-桥接(Bridge)设计模式

桥接设计模式 &#x1f6a9;什么是桥接设计模式&#xff1f;&#x1f6a9;桥接设计模式的特点&#x1f6a9;桥接设计模式的结构&#x1f6a9;桥接设计模式的优缺点&#x1f6a9;桥接设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是桥接设计模式…

【黑皮书】 AVL树

目录 前言 一 AVL树的介绍 二 单旋转 二 双旋转 总结 前言 AVL树的学习 一 AVL树的介绍 AVL树是带有平衡条件的二叉查找树&#xff0c;这个平衡条件要持续保持&#xff0c;而且必须保证树的深度为O(log(N))最简单的想法就是要求左右子树具有相同的高度 一棵AVL树是…

【机器学习】什么是决策树?

什么是决策树&#xff1f; 决策树是一种用于分类和回归问题的模型。它通过一系列的“决策”将数据逐步分裂&#xff0c;最终得出预测结果。可以把它看作是一个“树”&#xff0c;每个节点表示一个特征的判断&#xff0c;而每个分支代表了可能的判断结果&#xff0c;最终的叶子…

使用独立服务器的最佳方式指南

在寻找合适的主机服务方案时&#xff0c;可以考虑独立服务器&#xff0c;因为它拥有管理员权限以及更高的性能配置。在本指南中&#xff0c;我们将介绍独立服务器的多种用途&#xff0c;并分析为什么选择独立服务器可能是处理高性能、资源密集型应用和大流量网站的最佳方案。 搭…

【HTML 基础教程】HTML 属性

HTML 属性 属性是 HTML 元素提供的附加信息。 属性通常出现在 HTML 标签的开始标签中&#xff0c;用于定义元素的行为、样式、内容或其他特性。 属性总是以 name"value" 的形式写在标签内&#xff0c;name 是属性的名称&#xff0c;value 是属性的值。 HTML 属性 …

爬虫问题整理(2025.3.27)

此时此刻&#xff0c;困扰我一天的两个问题终于得到了解决&#xff0c;在此分享给大家。 问题1&#xff1a;使用anaconda prompt无法进行pip安装&#xff0c;这里只是一个示例&#xff0c;实际安装任何模块都会出现类似报错。 解决办法&#xff1a;关掉梯子......没错&#xf…

短信验证码安全需求设计

背景&#xff1a; 近期发现部分系统再短信充值频繁&#xff0c;发现存在恶意消耗短信额度现象&#xff0c;数据库表排查&#xff0c;发现大量非合法用户非法调用短信接口API导致额度耗尽。由于系统当初设计存在安全缺陷&#xff0c;故被不法分子进行利用&#xff0c;造成损失。…

若依专题——基础应用篇

若依搭建 搭建后端项目 ① Git 克隆并初始化项目 ② MySQL 导入与配置 ③ 启动 Redis 搭建后端项目注意事项&#xff1f; ① 项目初始化慢&#xff0c;执行clean、package ② MySQL导入后&#xff0c;修改application-druid.yml ③ Redis有密码&#xff0c;修改ap…

AI for CFD入门指南(传承版)

AI for CFD入门指南 前言适用对象核心目标基础准备传承机制 AI for CFDLibtorch的介绍与使用方法PytorchAutogluon MakefileVscodeOpenFOAMParaviewGambit 前言 适用对象 新加入课题组的硕士/博士研究生对AICFD交叉领域感兴趣的本科生实习生需要快速上手组内研究工具的合作研…

DeepSeek+RAG局域网部署

已经有很多平台集成RAG模式&#xff0c;dify&#xff0c;cherrystudio等&#xff0c;这里通过AI辅助&#xff0c;用DS的API实现一个简单的RAG部署。框架主要技术栈是Chroma,langchain,streamlit&#xff0c;答案流式输出&#xff0c;并且对答案加上索引。支持doc,docx,pdf,txt。…