ESP32S3网络编程学习笔记(1)—— Wi-Fi扫描实验

前言

(1)如果有嵌入式企业需要招聘湖南区域日常实习生,任何区域的暑假Linux驱动/单片机/RTOS的实习岗位,可C站直接私聊,或者邮件:zhangyixu02@gmail.com,此消息至2025年1月1日前均有效
(2)学习本文之前,建议先学习:ESP32S3网络编程学习笔记(0)—— 计算机网络基础科普

实操

工程目录和CMakeList修改

(1)在main文件夹中创建APP文件夹,并且在APP文件夹中创建wifi.cwifi.h两个文件。

在这里插入图片描述

(2)在main/CMakeLists.txt中修改为如下代码。

idf_component_register(SRC_DIRS "." "./app"INCLUDE_DIRS "." "./app")

在这里插入图片描述

WIFI程序配置

wifi.c

(1)在wifi.c中补充如下代码。

/******************************************************************************************************* @file     led.c* @brief    正点原子ESP32S3开发板的WIFI扫描实验* @author   zhangyixu* @version  1.0.0* @date     2024-04-06* @Copyright (c) 仅供学习,如需商用,请邮件zhangyixu02@gmail.com***************************************************************************************************** @attention* * 个人博客:www.zyxbeyourself.blog.csdn.net* 本人邮件:zhangyixu02@gmail.com***************************************************************************************************** @par Change Logs:* * Date Author Notes* 2024-04-06 zhangyixu 初始版本
*/#include "esp_log.h"
#include "esp_wifi.h"
#include "wifi.h"/* 存储12个WIFI名称 */
#define DEFAULT_SCAN_LIST_SIZE  10static const char *TAG = "WIFI";void wifi_init(void)
{/*-------------- 1、Wi-Fi/LwIP 初始化阶段 --------------*//* 1.1、网卡初始化,LWIP内核初始化 */ESP_ERROR_CHECK(esp_netif_init());/* 1.2、创建新的事件循环 */ESP_ERROR_CHECK(esp_event_loop_create_default());/* 1.3、用户初始化STA模式 */esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);/* wifi配置初始化 */wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));/*-------------- 2、Wi-Fi/LwIP 配置阶段 --------------*//* 设置WIFI为STA模式 */ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));/*-------------- 3、Wi-Fi/LwIP 启动阶段 --------------*//* 启动WIFI */ESP_ERROR_CHECK(esp_wifi_start());
}void wifi_scan(void)
{uint16_t number = DEFAULT_SCAN_LIST_SIZE;uint16_t ap_count = 0;wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE] = {0};/* 开始扫描附件的WIFI */esp_wifi_scan_start(NULL, true);/* 获取上次扫描中找到的AP数量 */ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));ESP_LOGI(TAG, "Total APs scanned = %u", ap_count);/* 获取上次扫描中找到的AP列表 */ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));/* 下面是打印附件的WIFI信息 */for (int i = 0; (i < number) && (i < ap_count); i++){ESP_LOGI(TAG, "NUM \t\t%d", i);ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid);ESP_LOGI(TAG, "RSSI \t\t%d", ap_info[i].rssi);ESP_LOGI(TAG, "MAC \t\t%02X-%02X-%02X-%02X-%02X-%02X\n", ap_info[i].bssid[0], ap_info[i].bssid[1], ap_info[i].bssid[2], ap_info[i].bssid[3], ap_info[i].bssid[4], ap_info[i].bssid[5]);}
}

wifi.h

(1)在wifi.h中补充如下代码。

/******************************************************************************************************* @file     led.h* @brief    正点原子ESP32S3开发板的WIFI扫描实验* @author   zhangyixu* @version  1.0.0* @date     2024-04-06* @Copyright (c) 仅供学习,如需商用,请邮件zhangyixu02@gmail.com***************************************************************************************************** @attention* * 个人博客:www.zyxbeyourself.blog.csdn.net* 本人邮件:zhangyixu02@gmail.com***************************************************************************************************** @par Change Logs:* Date Author Notes* 2024-04-06 zhangyixu 初始版本
*/#ifndef __WIFI_H__
#define __WIFI_H__#ifdef __cplusplusextern "C" {#endif /* __cplusplus *//*============================ INCLUDES ======================================*//*============================ MACROS ========================================*//*============================ TYPES =========================================*//*============================ GLOBAL VARIABLES ==============================*//*============================ PROTOTYPES ====================================*//*** @brief   将Wi-Fi初始化为sta并设置扫描方法** @param   无** @return  无*/void wifi_init(void);/*** @brief   进行WIFI扫描** @param   无** @return  无*/void wifi_scan(void);#ifdef __cplusplus}#endif /* __cplusplus */#endif /* __WIFI_H__ */

main.c

(1)在main.c中补充如下代码。

/******************************************************************************************************* @file     led.c* @brief    正点原子ESP32S3开发板的WIFI扫描实验* @author   zhangyixu* @version  1.0.0* @date     2024-04-06* @Copyright (c) 仅供学习,如需商用,请邮件zhangyixu02@gmail.com***************************************************************************************************** @attention* * 个人博客:www.zyxbeyourself.blog.csdn.net* 本人邮件:zhangyixu02@gmail.com***************************************************************************************************** @par Change Logs:* * Date Author Notes* 2024-04-06 zhangyixu 初始版本
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"#include "led.h"
#include "nvs_flash.h"
#include "wifi.h"void app_main(void)
{esp_err_t ret;ret = nvs_flash_init();             /* 初始化NVS */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();}led_init();             /* 初始化LED */wifi_init();wifi_scan();while(1){led_toggle();vTaskDelay(pdMS_TO_TICKS(1000));   /* 延时1s */}
}

运行结果

(1)烧录运行之后,能够一共扫描到多少个Wi-Fi,并且显示扫描到的前10个Wi-Fi名字,信号强度,MAC地址。

在这里插入图片描述

解析

为什么需要初始化NVS

(1)在esp_wifi_init()函数中,将会要使用到NVS相关内容,如果不先将NVS初始化,将无法成功读取到对应的内容,因此会导致初始化失败。
(2)如果我们不想使用NVS,可以打开menuconfig,按照下图关闭下图这个选项。

在这里插入图片描述

Wi-Fi配置初始化流程介绍

(1)在前面的计算机网络科普一文中我解释了APSTA的区别,因为本次实验是Wi-Fi扫描实验,因此我们需要将ESP32S3配置为STA模式。现在我们看看乐鑫科技官方给出来的STA模式配置流程。
(2)下图为截取部分,我们只需要看红框里面的内容即可。这个时候有人会问了,为什么只要看前三步呢?原因很简单,因为我们这里只会进行WIFI扫描,并不会进行连接操作,因此只需要看前三步骤。

在这里插入图片描述

1.初始化阶段

(1)上图,先看1.1步,我们知道需要初始化LwIPLwIP 是一个开源的 TCP/IP 协议栈,专门设计用于嵌入式系统。我们直接调用esp_netif_init()函数就可以将网卡LwIP内核进行初始化。

/* 1.1、网卡初始化,LWIP内核初始化 */
ESP_ERROR_CHECK(esp_netif_init());

(2)创建事件循环有两个函数esp_event_loop_create_default()esp_event_loop_create()函数。esp_event_loop_create_default()其实就是对esp_event_loop_create()进行了一层封装,没有特殊需求,一般调用esp_event_loop_create_default()
这个函数的调用是必要的,因为WIFI扫描实验需要在扫描过程中处理一些事件,例如扫描开始事件,扫描完成事件。如果没有创建事件循环,这些事件将无法被正确处理,导致Wi-Fi扫描实验无法正常进行。

/* 1.2、创建新的事件循环 */
ESP_ERROR_CHECK(esp_event_loop_create_default());

(3.1)前面说了,Wi-Fi扫描实验需要在扫描过程中处理一些事件。而这些事件由esp_netif_create_default_wifi_sta()函数创建。这个事件能够初始化Wi-FiSTA模式,官方的解释是创建有 TCP/IP 堆栈的默认网络接口实例绑定 station

/* 1.3、创建有 TCP/IP 堆栈的默认网络接口实例绑定 station */
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);

(3.2)这一步和上一步同属于1.3步骤,这里是 创建 Wi-Fi 驱动程序任务,并初始化 Wi-Fi 驱动程序。

/* 1.3、创建 Wi-Fi 驱动程序任务,并初始化 Wi-Fi 驱动程序 */
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

(4)这个时候肯定就有同学有疑问了,怎么没有1.4创建应用程序任务呢?原因很简单,我们这里只是进行 Wi-Fi 扫描,并不会进行连接,因此这一步进行省略。

1.2配置阶段

(1)这句话就是将 Wi-Fi配置为STA模式。如果不是在中国,可能还需要调用esp_wifi_set_xxx ()进行更多的配置,例如:协议模式、国家代码、带宽等。

/* 2、设置 Wi-Fi为STA模式 */
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

1.3启动阶段

(1)因为我们不需要连接Wi-Fi,因此无需关心 WIFI_EVENT_STA_CONNECTED 事件。只需要调用如下代码即可。

/* 3.1、启动 Wi-Fi 驱动程序 */
ESP_ERROR_CHECK(esp_wifi_start());

关键API介绍

esp_wifi_scan_start()

(1)这个函数表示开始扫描附近的Wi-Fi设备,我们先讲解一下esp_wifi_scan_start()第一个参数的作用。
<1>如果ssid不为NULL,则只扫描SSID与该值相同的AP。否则扫描所有SSIDAP
注:ssid就是Wi-Fi的名字。AP表示热点或者说是Wi-Fi。
<2>如果bssid不为NULL,则只扫描MAC地址与该值相同的AP
注:不了解MAC地址是什么意思的,请看上一篇计算机网络科普。
<3>如果channel为0,则进行全信道扫描。否则只扫描指定的信道。
<4>show_hidden如果为true则扫描时会包括隐藏SSIDAP。否则会忽略隐藏SSIDAP
<5>scan_type如果为WIFI_SCAN_TYPE_ACTIVE,则进行主动扫描。如果是WIFI_SCAN_TYPE_PASSIVE,则进行被动扫描。如下为主动扫描和被动扫描的区别。通常情况下,移动设备会优先使用主动扫描,而固定设备则更倾向于使用被动扫描

  • 主动扫描:客户端主动发送Probe Request帧,询问周围是否有APAP收到Probe Request后,会立即回复Probe Response帧,告知自己的信息。主动扫描速度更快,但会增加网络流量和功耗。
  • 被动扫描:客户端被动地监听AP周期性发送的Beacon帧。AP会定期广播Beacon帧,包含自身的SSID、安全性等信息。被动扫描速度较慢,但不会增加网络流量和功耗。
  • 区别:主动扫描可以发现隐藏SSIDAP,被动扫描无法发现。主动扫描可以更快地发现AP,但会增加功耗。被动扫描不会主动打扰AP,但可能会漏掉某些AP

<6>scan_time用于控制每个信道的扫描时间。对于被动描,scan_time.passive字段指定每个信道的扫描时间。对于主动扫描,每个信道的扫描时间由scan_time.active.minscan_time.active.max决定。
<7>home_chan_dwell_time用于控制在主信道上停留的时间。当进行快速扫描时,会优先在主信道上停留较长时间,以提高扫描效率。
(2)第二个参数就比较容易理解,如果是true那么需要等待Wi-Fi扫描完成之后才会进行esp_wifi_scan_start()下面的函数。如果是false,那么无需等待Wi-Fi扫描完成就会马上执行下面的任务。
(3)如果没有特殊需求,esp_wifi_scan_start()函数第一个参数一般填写NULL默认为主动扫描扫描所有通道扫描所有Wi-Fi忽略隐藏Wi-Fi主动扫描时间为0~120ms主信道上停留的时间为360ms

/*** @brief   扫描所有可用的 AP** @param    config    扫描的配置设置,如果设置为 NULL 将使用默认设置,默认值为 show_hidden:false、scan_type:active、scan_time.active.min:0、scan_time.active.max:120 毫秒、scan_time.passive :360 毫秒*          -block     如果true,此API将阻止调用者直到扫描完成,否则将立即返回** @return   ESP_OK                    配置成功*         - ESP_ERR_WIFI_NOT_INIT     WiFi未由esp_wifi_init初始化*         - ESP_ERR_WIFI_NOT_STARTED  esp_wifi_start未启动WiFi*         - ESP_ERR_WIFI_TIMEOUT      阻塞扫描超时*         - ESP_ERR_WIFI_STATE        调用esp_wifi_scan_start时wifi仍在连接*/
esp_err_t esp_wifi_scan_start(const wifi_scan_config_t *config, bool block);/** @brief 每个通道的活动扫描时间范围 */
typedef struct {uint32_t min;  /**< 每个通道的最小活动扫描时间,单位:毫秒 */uint32_t max;  /**< 每个通道的最大活动扫描时间,单位:毫秒,超过1500ms可能导致工作站与AP断开连接,不建议使用。  */
} wifi_active_scan_time_t;/** @brief 每个通道的主动和被动扫描时间的总和 */
typedef struct {wifi_active_scan_time_t active;  /**< 每个通道的主动扫描时间,单位:毫秒 */uint32_t passive;                /**< 每通道被动扫描时间,单位:毫秒,超过1500ms可能导致工作站与AP断开连接,不建议使用 */
} wifi_scan_time_t;/** @brief SSID扫描参数 */
typedef struct {uint8_t *ssid;               /**< SSID of AP */uint8_t *bssid;              /**< MAC address of AP */uint8_t channel;             /**< 通道,扫描特定的通道 */bool show_hidden;            /**< 使能扫描SSID隐藏的AP */wifi_scan_type_t scan_type;  /**< 扫描类型,主动或被动 */wifi_scan_time_t scan_time;  /**< 每通道扫描时间 */uint8_t home_chan_dwell_time;/**< 在扫描连续通道之间花费的时间*/
} wifi_scan_config_t;

esp_wifi_scan_get_ap_num()

(1)当我们使用esp_wifi_scan_start()函数扫描完Wi-Fi之后,我们可以利用这个函数获取道扫描道的Wi-Fi数量。

/*** @brief   获取上次扫描中找到的Wi-Fi数量** @param    number  存储上次扫描中找到的Wi-Fi数量** @return   ESP_OK                    获取成功*         - ESP_ERR_WIFI_NOT_INIT     Wi-Fi未由esp_wifi_init初始化*         - ESP_ERR_WIFI_NOT_STARTED  esp_wifi_start未启动Wi-Fi*         - ESP_ERR_INVALID_ARG       无效参数*/
esp_err_t esp_wifi_scan_get_ap_num(uint16_t *number);

esp_wifi_scan_get_ap_records()

(1)当我们调用esp_wifi_scan_start()函数

/*** @brief   获取上次扫描中找到的Wi-Fi列表** @param    number      设置ap_records可以容纳的最大Wi-Fi数量,如果number为10,但是扫描到的Wi-Fi只有4个,此时number会变成4。*         - ap_records  保存找到的Wi-Fi** @return   ESP_OK                    获取成功*         - ESP_ERR_WIFI_NOT_INIT     Wi-Fi未由esp_wifi_init初始化*         - ESP_ERR_WIFI_NOT_STARTED  esp_wifi_start未启动Wi-Fi*         - ESP_ERR_INVALID_ARG       无效参数*         - ESP_ERR_NO_MEM            内存不足*/
esp_err_t esp_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records);

Wi-Fi扫描流程介绍

(1)进行Wi-Fi扫描实验的前提是将ESP32设置为了STA模式,并且成功启动了Wi-Fi,否则无法进行Wi-Fi扫描实验。
(2)我们初始化完ESP32的Wi-Fi之后,就能够直接调用esp_wifi_scan_get_ap_num()函数进行扫描Wi-Fi了,需要注意的是,esp_wifi_scan_get_ap_num()的第二个参数需要配置为true,我们需要扫描完Wi-Fi之后再进行下一步操作。
(3)扫描到的Wi-Fi信息存储在wifi_ap_record_t结构体类型的数组里面,这个对于新手而言只需要关心三个参数:

  • ssid:Wi-Fi名字
  • rssi:一般来说,它是一个负数。RSSI值越大,表示信号强度越强,接近0RSSI值表示非常好的信号强度,而接近于-100RSSI值表示非常弱的信号强度。在某些情况下,如果使用的是其他类型的无线技术或者有特殊配置,RSSI可能会是正数。但对于大多数情况下,尤其是WiFi蓝牙等常见的无线通信,RSSI通常是负数。
  • bssid:Wi-FiMAC地址

参考

(1)乐鑫官方文档:ESP32-S3 Wi-Fi station 一般情况
(2)B站:WIFI扫描 - 乐鑫 ESP32 物联网开发框架 ESP-IDF 开发入门 - 孤独的二进制出品
(3)飞书:【立创·实战派ESP32-C3】开发板文档教程

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

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

相关文章

基于DPDK的VPP 插件demo代码

VPP的插件编写&#xff0c; 首先要把VPP 工程下载下来&#xff0c; 编译通过。 然后按照example程序的套中来编写插件。 还有一个前提&#xff0c; 就是测试机上已经具备了DPDK 已经可用版本。 1. 下载VPP。 可以从github上下载VPP的指定版本的zip包&#xff0c; 也可以用…

2024年租用阿里云服务器多少钱一年?连夜整理分享

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

__ne__()函数详解

在Python中&#xff0c;ne 是一个特殊方法&#xff0c;用于定义不等于&#xff08;!&#xff09;操作符的行为。当你使用 ! 操作符来比较两个类的实例时&#xff0c;Python会自动调用这个方法。如果这个方法没有在你的类中定义&#xff0c;那么 ! 操作符会使用 eq 方法的结果来…

【C++】C++ primer plus 第十二章--类和动态内存分配

动态内存和类 关于静态数据成员 类之作声明&#xff0c;不分配内存&#xff0c;因此静态成员变量在类中不能进行初始化&#xff0c;需要在类外进行。特殊情况&#xff1a; 存在可以在类中声明静态成员并初始化的情况&#xff0c;成员类型为const整型或者const枚举类型。 特殊…

软考高级架构师:嵌入式系统的内核架构

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

2024/4/1—力扣—二叉树的最近公共祖先

代码实现&#xff1a; 思路&#xff1a; 递归判断左子树和右子树&#xff0c;查找p或者q是否在当前节点的子树上 1&#xff0c;在同一子树上&#xff0c;同一左子树&#xff0c;返回第一个找到的相同值&#xff0c;同一右子树上&#xff0c;返回第一个找到的相同值 2&#xff0…

Oracle23免费版简易安装攻略

installation-guide 1 安装 root用户下 wget https://yum.oracle.com/repo/OracleLinux/OL8/developer/x86_64/getPackage/oracle-database-preinstall-23c-1.0-1.el8.x86_64.rpm wget https://download.oracle.com/otn-pub/otn_software/db-free/oracle-database-free-23c-1…

UML 绘制工具 starUML 入门介绍

拓展阅读 常见免费开源绘图工具 OmniGraffle 创建精确、美观图形的工具 UML-架构图入门介绍 starUML UML 绘制工具 starUML 入门介绍 PlantUML 是绘制 uml 的一个开源项目 UML 等常见图绘制工具 绘图工具 draw.io / diagrams.net 免费在线图表编辑器 绘图工具 excalidr…

linux lua版本升级

要在Linux上升级Lua到5.4版本&#xff0c;你需要执行以下步骤&#xff1a; 1、下载Lua 5.4源代码&#xff1a; 首先&#xff0c;你需要从Lua的官方网站下载Lua 5.4的源代码。你可以访问Lua的官方网站或使用wget或curl命令从命令行下载。 wget http://www.lua.org/ftp/lua-5.4.x…

工具推荐-针对Nacos利器-NacosExploitGUI_v4.0

Nacos是由阿里所开发的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 工具简介 集成Nacos的各种poc Nacos控制台默认口令漏洞(nacos,nacos)Nacostoken.secret.key默认配置(QVD-2023-6271)Nacos-clientYaml反序列化漏洞Nacos Jraft Hessian反序列化漏洞…

代码随想录算法训练营第46天|139.单词拆分|关于多重背包,你该了解这些!|背包问题总结篇!

代码随想录算法训练营第46天|139.单词拆分|关于多重背包&#xff0c;你该了解这些&#xff01;|背包问题总结篇&#xff01; 详细布置 关于 多重背包&#xff0c;力扣上没有相关的题目&#xff0c;所以今天大家的重点就是回顾一波 自己做的背包题目吧。 139.单词拆分 视频讲…

PET-SQL:基于大模型的两阶段Text2SQL方法

简介 PET-SQL出自论文《PET-SQL: A Prompt-enhanced Two-stage Text-to-SQL Framework with Cross-consistency》&#xff0c;将基于大模型的Text2SQL分为两个阶段进行&#xff0c;在第一阶段使用数据表schema信息、数据表采样数据、相似问答问答对生成初步的SQL(PreSQL)&…

【边缘智能】00_边缘计算发展背景

本系列是个人学习《边缘就算基础知识入门》的笔记&#xff0c;仅为个人学习记录&#xff0c;欢迎交流&#xff0c;感谢批评指正 移动物联设备产生海量数据&#xff0c;数据密集型移动智能应用&#xff0c;计算密集、动态性高&#xff0c;实时性强 传统云计算架构 基于广域互联…

大学课堂点名程序

大学课堂点名程序 from gtts import gTTS import os import tkinter as tk import pygame import csv import random from datetime import datetime from tkinter import messagebox from tkinter import simpledialog input_data="student1" def langDu(text):tts…

matrix-breakout-2-morpheus 靶机渗透

信息收集&#xff1a; 1.nmap存活探测&#xff1a; nmap -sn -r 192.168.10.1/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-06 12:13 CST Nmap scan report for 192.168.10.1 Host is up (0.00056s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap…

鸿蒙内核源码分析 (双向链表篇) | 谁是内核最重要结构体

双向链表是什么&#xff1f; 谁是鸿蒙内核最重要的结构体 &#xff1f; 一定是: LOS_DL_LIST(双向链表)&#xff0c; 它长这样。 typedef struct LOS_DL_LIST {struct LOS_DL_LIST *pstPrev; /**< Current nodes pointer to the previous node | 前驱节点(左手)*/struct L…

Qt实现Kermit协议(四)

3 实现 3.3 KermitRecvFile 该模块实现了Kermit接收文件功能。 序列图如下&#xff1a; 3.3.1 KermitRecvFile定义 class QSerialPort; class KermitRecvFile : public QObject, public Kermit {Q_OBJECT public:explicit KermitRecvFile(QSerialPort *serial, QObject *…

题目 1847: 字符串中间和后边*号删除

题目描述: 假定输人的字符串中只包含字母和*号。请编写函数fun(  )&#xff0c;它的功能是&#xff1a;除了字符串前导的*号之外&#xff0c;将串中其他*号全部删除。在编写函数时&#xff0c;不得使用C语言提供的字符串函数。 代码: package lanqiao;import java.math.Bi…

面试(03)————多线程和线程池

一、多线程 1、什么是线程?线程和进程的区别? 2、创建线程有几种方式 &#xff1f; 3、Runnable 和 Callable 的区别&#xff1f; 4、如何启动一个新线程、调用 start 和 run 方法的区别&#xff1f; 5、线程有哪几种状态以及各种状态之间的转换&#xff1f; 6、线程…

RIP协议

路由信息协议。 分为v1和v2 1、标准的距离矢量型协议 2、使用跳数作为度量&#xff0c;默认优先级为100 3、v1为有类别版本&#xff0c;v2为无类别版本&#xff08;无类别自定义掩码&#xff09; 4、周期更新触发更新。 v1和v2的区别 1、v1不携带子网掩码——不支持子网划…