设为首页 加入收藏

TOP

ESP32-两种有趣的wifi连接方式(一)
2023-07-23 13:31:13 】 浏览:315
Tags:ESP32- wifi 连接方

前言

之前毕设的时候做了一个ESP32有关的项目,当时采用的WiFi连接方式是利用SD卡将WiFi信息写入txt文件存入SD卡中,利用文件系统读取WiFi信息。

现在想想这个方法修改WiFi太过于麻烦,如果每次换一个地方,首先先要用一个设备修改SD卡中的文件信息,才能连接上WiFi。

在最近的学习过程中了解到两种较为有趣的连接WiFi的方式:

  • 强制门户认证
  • Smart Config

本文就以这两种方式展开讨论。

强制门户认证

1.什么是强制门户认证

背景

在日常我们登录到一些公共的WiFi例如学校的校园网,酒店WiFi的时候,虽然这些WiFi都是没有密码的,但是每当你连接后都会自动弹出一个网页,输入一些信息后才允许你上网。而连接到热点自动弹出网页这部分操作就是强制门户认证

原理

APP在访问某个域名的时候,会先发起DNS请求,向服务器问域名的IP地址。然后再发起HTTP请求,请求想要的内容。

在这里,由于nodemcu充当了AP的角色,可以接收到APP发起的DNS请求包。只要让nodemcu把回复请求的IP地址指向自己的IP就行了。这样一来,APP就会向设备IP发起HTTP请求。那么,nodemcu在收到HTTP请求后,不管对方请求什么内容,都回复本地的HTML文件。手机就会弹出页面,

2.实现强制门户

从上面原理可以看的出来,需要实现一个DNS服务器和一个TCP服务器,当然还需要一个HTML来实现一个网页。接下来分别介绍这些功能。

DNS服务器

关于DNS是啥,想必学过计算机网络的应该都知道,它是Domain Name System的简写,中文翻译过来就是域名系统,是用来将主机名转换为ip的。

问:为什么会有DNS,或者说为什么要弄出两种方式(主机名和IP地址)来标识一台主机呢?

答:这是因为主机名便于人的记忆,而IP地址便于计算机网络设备的处理,于是需要DNS来做前者到后者的转换。

DNS实际上是由一个分层的DNS服务器实现的分布式数据库和一个让主机能够查询分布式数据库的应用层协议组成。详细查看这篇文章

建立完DNS服务器后,所有APP的DNS请求,都会得到一个带本设备IP地址的响应包。接下来APP将会向这个IP地址发起HTTP请求。

TCP服务器

为了能够响应HTTP请求,需要使用net模块创建一个TCP实例。除非有特殊指定,不然访问的都是80端口。所以,只要创建一个监听80端口的TCP实例即可。那些非80端口的请求就不要理会了。

TCP服务器的工作很简单,当监听到有来自80端口的请求的时候,就把HTML文件回复出去。也不用过对方的请求是什么,抓到一个回一个,简单粗暴。

HTML页面

最后,还差一个HTML文件。这个文件的内容也很简单。不过涉及前端的内容了,不打算细说。

HTML页面可以通过Cmake的编译方式编译成一个大数组在C语言中调用,后面会详细说明。

3.代码展示

本人后面代码仅供参考,大多数都是从网上白嫖下来的。这里提供一下参考网站。完整工程目录后面给出。

DNS服务器

/*
 * @Author: tangwc
 * @Date: 2022-10-28 10:18:55
 * @LastEditors: tangwc
 * @LastEditTime: 2022-11-13 16:21:21
 * @Description:
 * @FilePath: \esp32_wifi_link\components\dns_server\dns_server.c
 *
 *  Copyright (c) 2022 by tangwc, All Rights Reserved.
 */
#include <string.h>
#include <sys/param.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_log.h"
#include "esp_system.h"
#include "esp_netif.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"

#include "dns_server.h"

#define DNS_PORT (53)
#define DNS_MAX_LEN (256)

#define OPCODE_MASK (0x7800)
#define QR_FLAG (1 << 7)
#define QD_TYPE_A (0x0001)
#define ANS_TTL_SEC (300)

static const char *TAG = "DNS_SERVER";
// DNS报头数据包
typedef struct __attribute__((__packed__))
{
    uint16_t id;
    uint16_t flags;
    uint16_t qd_count;
    uint16_t an_count;
    uint16_t ns_count;
    uint16_t ar_count;
} dns_header_t;

// DNS问题包
typedef struct
{
    uint16_t type;
    uint16_t class;
} dns_question_t;

// DNS答案包
typedef struct __attribute__((__packed__))
{
    uint16_t ptr_offset;
    uint16_t type;
    uint16_t class;
    uint32_t ttl;
    uint16_t addr_len;
    uint32_t ip_addr;
} dns_answer_t;

/**
 * @description: 将数据包中的名称从DNS名称格式解析为常规分隔的名称,
 * @param {char} *raw_name
 * @param {char} *parsed_name
 * @param {size_t} parsed_name_max_len
 * @return {*} 返回 数据包中下一部分的指针。
 */
static char *parse_dns_name(char *raw_name, char *parsed_name, size_t parsed_name_max_len)
{

    char *label = raw_name;
    char *name_itr = parsed_name;
    int name_len = 0;
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇OpenOCD + DAP-LINK调试ESP32的失.. 下一篇预编译#error的使用

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目