当前位置: 首页 > news >正文

ESP-IDF:TCP多线程并发服务器

核心代码:

核心思想就是主线程只处理socket监听功能,把数据处理部分分配到不同的线程中去处理。来了一个客户端连接,就分配新的线程去处理该客户端的数据请求。
在这里插入图片描述

代码:

/多线程并发服务器/
#include <stdio.h>
#include “sdkconfig.h”
#include “freertos/semphr.h”
#include “esp_system.h”
#include “esp_spi_flash.h”
#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_event_loop.h”
#include “esp_log.h”
#include “nvs_flash.h”
#include “sdkconfig.h”

#include “lwip/err.h”
#include “lwip/sys.h”

#include “mdns.h”

#include <sys/param.h>
#include “esp_event.h”

#include “esp_netif.h”
//#include “protocol_examples_common.h”

#include “lwip/sockets.h”
#include <lwip/netdb.h>

/* The examples use WiFi configuration that you can set via ‘make menuconfig’.

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_ESP_WIFI_AP_SSID CONFIG_ESP_WIFI_AP_SSID
#define EXAMPLE_ESP_WIFI_AP_PASS CONFIG_ESP_WIFI_AP_PASSWORD
#define EXAMPLE_MAX_STA_CONN CONFIG_MAX_STA_CONN
#define EXAMPLE_IP_ADDR CONFIG_SERVER_IP
#define EXAMPLE_ESP_WIFI_AP_CHANNEL CONFIG_ESP_WIFI_AP_CHANNEL

static const char *TAG = “camera wifi”;
static const char *TAG1 = “michael add:”;

static int s_retry_num = 0;

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
case SYSTEM_EVENT_AP_STACONNECTED:
ESP_LOGI(TAG, “station:” MACSTR " join, AID=%d",
MAC2STR(event->event_info.sta_connected.mac),
event->event_info.sta_connected.aid);
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
ESP_LOGI(TAG, “station:” MACSTR “leave, AID=%d”,
MAC2STR(event->event_info.sta_disconnected.mac),
event->event_info.sta_disconnected.aid);
break;
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGI(TAG, “got ip:%s”,
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
s_retry_num = 0;
break;
case SYSTEM_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”);
}
ESP_LOGI(TAG,“connect to the AP fail”);
break;
}
default:
break;
}
ESP_LOGI(TAG1,“before mdns_handle_system_event”);
mdns_handle_system_event(ctx, event);
ESP_LOGI(TAG1,“after mdns_handle_system_event”);
return ESP_OK;
}

void wifi_init_softap()
{
if (strcmp(EXAMPLE_IP_ADDR, “192.168.4.1”))
{
int a, b, c, d;
sscanf(EXAMPLE_IP_ADDR, “%d.%d.%d.%d”, &a, &b, &c, &d);
tcpip_adapter_ip_info_t ip_info;
IP4_ADDR(&ip_info.ip, a, b, c, d);
IP4_ADDR(&ip_info.gw, a, b, c, d);
IP4_ADDR(&ip_info.netmask, 255, 255, 255, 0);
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(WIFI_IF_AP));
ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(WIFI_IF_AP, &ip_info));
ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(WIFI_IF_AP));
}
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config_t));
snprintf((char*)wifi_config.ap.ssid, 32, “%s”, EXAMPLE_ESP_WIFI_AP_SSID);
wifi_config.ap.ssid_len = strlen((char*)wifi_config.ap.ssid);
snprintf((char*)wifi_config.ap.password, 64, “%s”, EXAMPLE_ESP_WIFI_AP_PASS);
wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN;
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
if (strlen(EXAMPLE_ESP_WIFI_AP_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
if (strlen(EXAMPLE_ESP_WIFI_AP_CHANNEL)) {
int channel;
sscanf(EXAMPLE_ESP_WIFI_AP_CHANNEL, “%d”, &channel);
wifi_config.ap.channel = channel;
}

ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s",EXAMPLE_ESP_WIFI_AP_SSID, EXAMPLE_ESP_WIFI_AP_PASS);

}

void wifi_init_sta()
{
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config_t));
snprintf((char*)wifi_config.sta.ssid, 32, “%s”, EXAMPLE_ESP_WIFI_SSID);
snprintf((char*)wifi_config.sta.password, 64, “%s”, EXAMPLE_ESP_WIFI_PASS);

ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );ESP_LOGI(TAG, "wifi_init_sta finished.");
ESP_LOGI(TAG, "connect to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);

}

void app_wifi_main()
{
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
wifi_mode_t mode = WIFI_MODE_AP;

if (strlen(EXAMPLE_ESP_WIFI_AP_SSID) && strlen(EXAMPLE_ESP_WIFI_SSID)) {mode = WIFI_MODE_APSTA;
} else if (strlen(EXAMPLE_ESP_WIFI_AP_SSID)) {mode = WIFI_MODE_AP;
} else if (strlen(EXAMPLE_ESP_WIFI_SSID)) {mode = WIFI_MODE_STA;
}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);if (mode == WIFI_MODE_NULL) {ESP_LOGW(TAG,"Neither AP or STA have been configured. WiFi will be off.");return;
}tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_mode(mode));if (mode & WIFI_MODE_AP) {wifi_init_softap();
}if (mode & WIFI_MODE_STA) {wifi_init_sta();
}
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));

}

/* BSD Socket API 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.
*/

#define PORT CONFIG_EXAMPLE_PORT
#define KEEPALIVE_IDLE CONFIG_EXAMPLE_KEEPALIVE_IDLE
#define KEEPALIVE_INTERVAL CONFIG_EXAMPLE_KEEPALIVE_INTERVAL
#define KEEPALIVE_COUNT CONFIG_EXAMPLE_KEEPALIVE_COUNT

//static const char *TAG = “example”;

//static void do_retransmit(const int sock)
static void do_retransmit0(const int sock) //michael change for multitasks server
{
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;char data[]="task0 reply";//michael add for multitasks serverwhile (to_write > 0) {int written = send(sock, rx_buffer + (len - to_write), to_write, 0);written += send(sock, data, sizeof(data), 0);//michael add for multitasks serverif (written < 0) {ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);}to_write -= written;}}
} while (len > 0);
shutdown(sock, 0); //michael add for multitasks server
close(sock);//michael add for multitasks server

}

static void do_retransmit1(const int sock) //michael change for multitasks server
{
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;char data[]="task1 reply"; //michael add for multitasks serverwhile (to_write > 0) {int written = send(sock, rx_buffer + (len - to_write), to_write, 0);written += send(sock, data, sizeof(data), 0);//michael add for multitasks serverif (written < 0) {ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);}to_write -= written;}}
} while (len > 0);
shutdown(sock, 0); //michael add for multitasks server
close(sock);//michael add for multitasks server

}

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;

if (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;
}

#ifdef CONFIG_EXAMPLE_IPV6
else if (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;
}
#endif

int 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));
#endif

ESP_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;
}int sockid[3];//保存主线程收到的sock, michael add for 多线程
int i=0;//保存主线程收到的sock, michael add for 多线程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);ESP_LOGI(TAG, "michael add before accept");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;}ESP_LOGI(TAG, "michael add after accept");// 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 stringif (source_addr.ss_family == PF_INET) {inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);}

#ifdef CONFIG_EXAMPLE_IPV6
else if (source_addr.ss_family == PF_INET6) {
inet6_ntoa_r(((struct sockaddr_in6 )&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
}
#endif
ESP_LOGI(TAG, “Socket accepted ip address: %s”, addr_str);
//把下面三个操作放到子线程中去处理,实现并行
sockid[i] = sock;
switch (i)
{
case 0:
xTaskCreate(do_retransmit0, “transmit_task0”, 4096, sockid[0], 15, NULL);
break;
case 1:
xTaskCreate(do_retransmit1, “transmit_task1”, 4096, sockid[1], 15, NULL);
break;
default:
ESP_LOGI(TAG1, “only can accept 2 connector”);
break;
}
i++;
/
单线程server代码
do_retransmit(sock);

    shutdown(sock, 0);close(sock);*/
}

CLEAN_UP:
close(listen_sock);
vTaskDelete(NULL);
}

void test25() {
app_wifi_main();
#ifdef CONFIG_EXAMPLE_IPV4
xTaskCreate(tcp_server_task, “tcp_server”, 4096, (void*)AF_INET, 15, NULL);
#endif
#ifdef CONFIG_EXAMPLE_IPV6
xTaskCreate(tcp_server_task, “tcp_server”, 4096, (void*)AF_INET6, 5, NULL);
#endif
}

void app_main(void)
{

// /* Print chip information */
// esp_chip_info_t chip_info;
// esp_chip_info(&chip_info);
// printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
//        CONFIG_IDF_TARGET,
//        chip_info.cores,
//        (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
//        (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");// printf("silicon revision %d, ", chip_info.revision);// printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
//        (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");// printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size());// for (int i = 10; i >= 0; i--)
// {
//     printf("Restarting in %d seconds...\n", i);
//     vTaskDelay(1000 / portTICK_PERIOD_MS);
// }
// printf("Restarting now.\n");
// fflush(stdout);
// printf("----test 23----\n");
// test23();// printf("----test 24 基于计数型信号量的生产者和消费者模型代码----\n");
// test24();// esp_restart();
test25();

}

结果:

电脑端tcp client向esp server发送数据,server端把数据回传并添加是哪个线程发送的。
在这里插入图片描述

相关文章:

ESP-IDF:TCP多线程并发服务器

核心代码&#xff1a; 核心思想就是主线程只处理socket监听功能&#xff0c;把数据处理部分分配到不同的线程中去处理。来了一个客户端连接&#xff0c;就分配新的线程去处理该客户端的数据请求。 代码&#xff1a; /多线程并发服务器/ #include <stdio.h> #include …...

Springboot扩展点之SmartInitializingSingleton

前言这篇文章会重点分析一下SmartInitializingSingleton扩展点的功能 特性、实现方式 、工作原理。SmartInitializingSingleton扩展点内只有一个扩展方法&#xff0c;且执行时机在Spring Bean的生命周期里比较靠后&#xff0c;很重要&#xff0c;但是也很简单。功能特性1、Smar…...

基于linux内核的驱动开发学习

1 驱动 定义&#xff1a;驱使硬件动起来的程序 种类&#xff1a;裸机驱动&#xff1a;需求分析--》查原理图--》查芯片手册--》code 系统驱动&#xff1a;需求分析--》查原理图--》查芯片手册--》设备树--》code --》安装到内核中…...

python3 django gunicorn

首先&#xff0c;Gunicorn是一个高效的Web服务器&#xff0c;地位相当于Java中的Tomcat。简单来说gunicorn封装了HTTP的底层实现&#xff0c;我们通过gunicorn启动服务&#xff0c;用户请求与服务相应都经过gunicorn传输。下载gunicorn的方法也比较简单&#xff0c;在django工程…...

专家分享 | 租赁型售楼处标准化示范区提效研究

2023年2月8日上午&#xff0c;优积科技邀请原金地集团北京公司 高级室内设计专业应锎经理为我司团队分享《租赁型售楼处标准化示范区提效》的专题。 此次专家分享课题加上大家踊跃讨论时间长达3小时&#xff0c;会上应总详细介绍了租赁型售楼处标准化示范区提效&#xff0c;需…...

linux之echo使用技巧

参考文章&#xff1a;linux基本功系列-echo命令实战一、echo 命令是什么&#xff1f;作用&#xff1a; echo命令能将指定文本显示在Linux命令行上&#xff0c;或者通过重定向符写入到指定的文件中。语 法&#xff1a;echo [-ne][字符串] / echo [–help][–version]补充说明&am…...

Keras实例教程(7)之构建模型的第三种方式

多年以前,在TensorFlow中搭建深度学习模型对于很多人来说其实仍然是比较困难的。相比之下,Keras作为独立于TensorFlow的一种深度学习框架则要简单很多。在TensorFlow与PyTorch的竞争中逐渐式微的情况下,TensorFlow团队终于宣布Keras将成为在tensorflow2.0中构建和训练模型的…...

【JUC并发编程】18 CopyOnWriteArrayList源码也就够看2分钟

文章目录1、CopyOnWriteArrayList概述2、原理 / 源码1&#xff09;构造函数2、add()3&#xff09;get()4&#xff09;remove()5&#xff09;iterator()1、CopyOnWriteArrayList概述 CopyOnWriteArrayList相当于线程安全的ArrayList&#xff0c;底层是一个可变数组。 特点如下…...

如何优雅的实现回调函数?

本篇文章又是一期优雅的代码编程介绍———回调函数。 传统的nodejs编程都是这样的 const fs require(fs) fs.readFile(test.txt,utf8, function(err, dataStr){if(err){} }) 嵌套层级如果多了就成回调地狱了。如果我们将这种风格的代码转换成这样呢&#xff1f; const fs …...

3GPP-NR Band20标准定义频点和信道(3GPP V17.7.0 (2022-12))

Reference test frequencies for NR operating band n20 Table 4.3.1.1.1.20-1: Test frequencies for NRoperating band n20 and SCS 15 kHz CBW [MHz]carrierBandwidth...

Excel表格的公式不想显示出来,可以这样操作

在制作Excel表格的时候&#xff0c;很多人做数据会用到函数公式&#xff0c;这些编辑都是默认可以看到的。 但有时候我们不想让他人看到自己的计算思路和所用公式&#xff0c;有没有办法可以隐藏公式&#xff0c;只显示数据呢&#xff1f;答案是肯定的&#xff0c;今天我们就来…...

【零基础入门前端系列】—语义化标签、实体字符、视频、音频(八)

【零基础入门前端系列】—语义化标签、实体字符、视频、音频&#xff08;八&#xff09; 一、什么是HTML语义化标签 语义化的标签&#xff0c;旨在让标签有自己的含义 如上代码&#xff1a;p标签与span标签的区别之一就是&#xff0c;p标签的含义是段落而span标签没有独特的…...

超详细讲解线性表和顺序表!!

超详细讲解线性表和顺序表&#xff01;&#xff01;线性表顺序表顺序表的概念及结构静态顺序表动态顺序表顺序表接口实现1、创建2、初始化3、扩容4、尾插5、打印6、销毁7、尾删8、头插9、头删10、插入任意位置11、删除任意位置12、查找13、修改线性表 线性表&#xff08;linea…...

大数据之-Nifi-Nifi的安装_启动_认识Nifi的操作台---大数据之Nifi工作笔记0002

然后我们看一下如何安装nifi 这个上一节已经说了 然后看一下环境准备,这个自己去安装就可以了,需要jdk,1.8就可以了,然后 maven安装上就可以了 然后去下载,这里下载Linux版本的 1.9.2的版本比较稳定 下载以后,避免端口冲突要修改端口默认是8080,修改为58080 然后启动很简单,看…...

【大数据clickhouse】clickhouse 常用查询优化策略详解

一、前言 在上一篇我们分享了clickhouse的常用的语法规则优化策略&#xff0c;这些优化规则更多属于引擎自带的优化策略&#xff0c;开发过程中只需尽量遵守即可&#xff0c;然而&#xff0c;在开发过程中&#xff0c;使用clickhouse更多将面临各种查询sql的编写甚至复杂sql的…...

【Java项目】基于Java+MySQL+Tomcat+maven+Servlet的个人博客系统的完整分析

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【Java项目】 ✈️✈️本篇内容:个人博客系统前后端分离实现&#xff01; &#x1f680;&#x1f680;个人代码托管github&#xff1a;博客系统源码地址&#xff…...

java 程序员怎么做找工作

java 程序员怎么做找工作 在网络招聘网站上搜索职位。在中国&#xff0c;像智联招聘、前程无忧、猎聘网等招聘网站上&#xff0c;有许多公司在招聘JAVA程序员。通过这些网站可以快速找到自己合适的工作。 关注社交媒体和专业网站。 加入一些面向JAVA程序员的社交媒体和专业网…...

S7-1200对于不同项目下的PLC之间进行开放式以太网通信的具体方法示例

S7-1200对于不同项目下的PLC之间进行开放式以太网通信的具体方法示例 如下图所示,打开TIA博途创建一个新项目,并通过“添加新设备”组态 S7-1200 客户端 ,选择 CPU1214C DC/DC/DC (client IP:192.168.0.102),建立新子网; 首先编写客户端程序:打开OB1编程界面,选择指令…...

操作系统(四):磁盘调度算法,先来先服务,最短寻道时间优先,电梯算法

文章目录一、磁盘结构二、先来先服务三、最短寻道时间优先四、电梯算法 SCAN一、磁盘结构 盘面&#xff08;Platter&#xff09;&#xff1a;一个磁盘有多个盘面&#xff1b; 磁道&#xff08;Track&#xff09;&#xff1a;盘面上的圆形带状区域&#xff0c;一个盘面可以有多…...

maven解决包冲突简单方式(插件maven helper | maven指令)

文章目录使用idea插件maven helper使用maven指令在Java开发中&#xff0c;常常会遇到不同jar包之间存在冲突的情况&#xff0c;这可能会导致编译错误、运行时异常等问题。 使用idea插件maven helper 在idea安装插件maven helper 安装重启完之后点击pom文件&#xff0c;有一个De…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...

高保真组件库:开关

一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...

react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)

之前都是使用react-pdf来渲染pdf文件&#xff0c;这次有个需求是要兼容xp环境&#xff0c;xp上chrome最高支持到49&#xff0c;虽然说iframe或者embed都可以实现预览pdf&#xff0c;但为了后续的定制化需求&#xff0c;还是需要使用js库来渲染。 chrome 49测试环境 能用的测试…...