3.wifi开发,网络编程
网络协议栈LwIP
WiFi UDP Clinet编程
WiFi UDP Server编程
WiFi TCP Client编程
WiFi TCP Server编程
一。LWIP原理介绍,API介绍,文件结构
1.Lwip支持的协议

2.API

3.文件结构
1.api目录:应用程序接口文件。
2.arch目录:与硬件和OS有关的文件,包括网络驱动、移植需要修改的文件。
3.core目录:LwIP的核心代码,包括ICMP、IP、UDP、TCP等协议的实现等。
4.include目录:LwIP的包含文件。
5.netif目录:PPP协议和LwIP网络设备驱动程序的模板,提供了网络接口驱动程序的基本框架。
4.Socket 通信模型
Socket是一个网络编程接口
Socket类型:
(1)流式套接字(SOCK_STREAM)
(2)数据报套接字(SOCK_DGRAM)
(3)原始套接字(SOCK_RAW)
5.Socket API
socket:创建一个套接字
bind:将本地端口号和IP地址绑定到套接字上
listen:TCP监听
accept:TCP监听接受处理
connect:TCP客户端连接
select:特殊套接字设置
send/sendto:发送数据包到已连接/未连接套接字上
recv/recvfrom:接收数据包从已连接/未连接套接字上
getsockopt/setsockopt:获取/改变套接字选项
getpeername/getsockname:获取远端/本地地址信息
close:关闭套接字
shutdown:按设置关闭套接字
gethostbyname/gethostbyaddr:地址域名映射
read:从套接字缓存读数据
write:向套接字缓存写数据
目的:
Lwip协议栈的实现目的,无非是要上层用来实现app的socket编程。 为了兼容性,lwip的socket通过宏定义提供标准的socket接口函数
5.介绍常用的API
(1)int socket (int domain, int type, int protocol);
1.domain 是地址族
PF_INET // internet IPv4协议
PF_INET6 // internet IPv6协议
PF_UNSPEC // 用户协议
2.type // 套接字类型
SOCK_STREAM // 流式套接字
SOCK_DGRAM // 数据报套接字 S
OCK_RAW // 原始套接字
3.protocol //参数通常置为0
IPPROTO_IP 0
IPPROTO_TCP 6
IPPROTO_UDP 17
(2)int bind (int sockfd, struct sockaddr* addr, int addrLen);
1.sockfd 由socket() 调用返回
2.addr 是指向 sockaddr_in 结构的指针,包含本机IP 地址和端口号
struct sockaddr_in{
u_short sin_family // protocol family
u_short sin_port // port number
}
struct in_addr sin_addr //IP address (32-bits)
3.addrLen : sizeof (struct sockaddr_in)
(3)地址结构
地址的数据结构
通用地址结构struct sockaddr{ u_short sa_family; // 地址族, AF_xxxchar sa_data[14]; // 14字节协议地址};Internet协议地址结构struct sockaddr_in{ u_short sin_family; // 地址族, AF_INET,2 bytesu_short sin_port; // 端口,2 bytesstruct in_addr sin_addr; // IPV4地址,4 bytes char sin_zero[8]; // 8 bytes unused,作为填充};
IPv4地址结构
// internet address
struct in_addr
{in_addr_t s_addr; // u32 network address
};
使用方法
1.定义一个struct sockaddr_in类型的变量并清空
struct sockaddr_in myaddr; memset(&myaddr, 0, sizeof(myaddr));2.填充地址信息
myaddr.sin_family = PF_INET; myaddr.sin_port = htons(8888); myaddr.sin_addr.s_addr = inet_addr(“192.168.1.100”);3.将该变量强制转换为struct sockaddr类型在函数中使用
bind(listenfd, (struct sockaddr*)(&myaddr), sizeof(myaddr));
(4)地址转换函数
1.unsigned long inet_addr(char *address);
address是以’\0’结尾的点分IPv4字符串。该函数返回32位的地址。如果字符串包含的不是合法的IP地址,则函数返回-1。例如:
struct in_addr addr; addr.s_addr = inet_addr(" 192.168.1.100 ");
2.char* inet_ntoa(struct in_addr address);
address是IPv4地址结构,函数返回一指向包含点分IP地址的静态存储区字符指针。如果错误则函数返回NULL。
(5)获取/发送套接字
获取套接字
int getsockopt(int sock, int level,int optname, void *optval, socklen_t *optlen);
发送套接字
int setsockopt(int sock, int level,int optname, const void *optval, socklen_t optlen);
参数:
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。
返回说明: 成功执行时,返回0。
失败返回-1,errno被设为以下的某个值
EBADF:sock不是有效的文件描述词
EFAULT:optval指向的内存并非有效的进程空间
EINVAL:在调用setsockopt()时,optlen无效
ENOPROTOOPT:指定的协议层不能识别选项
ENOTSOCK:sock描述的不是套接字
(6)listen监听
int listen (int sockfd, int backlog);
sockfd:监听连接的套接字。
backlog 指定了正在等待连接的最大队列长度,它的作用在于处理可能同时出现的几个连接请求。 DoS(拒绝服务)攻击即利用了这个原理,非法的连接占用了全部的连接数,造成正常的连接请求被拒绝。 返回值: 0 或 -1。
完成listen()调用后,socket变成了监听socket(listening socket).
(7)accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) ;
返回值:已建立好连接的套接字或-1
sockfd : 监听套接字
addr : 对方地址
addrlen:地址长度
(8)connect
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
返回值:0 或 -1
sockfd : socket返回的文件描述符
serv_addr : 服务器端的地址信息
addrlen : serv_addr的长度
(9)send/sendto
ssize_t send(int socket, const void *buffer, size_t length, int flags);
ssize_t sendto(int s, const void *data, size_t size, int flags,const struct sockaddr *to, socklen_t tolen);
返回值: 成功:实际发送的字节数 失败:-1, 并设置errno
头文件: #include <sys/socket.h>
buffer : 发送缓冲区首地址 length : 发送的字节数 flags : 发送方式(通常为0)
(10)recv/recvfrom
ssize_t recv(int socket, const void *buffer, size_t length, int flags);
ssize_t recvfrom(int s, void *mem, size_t len, int flags,struct sockaddr *from, socklen_t *fromlen);
返回值: 成功:实际接收的字节数 失败:-1,并设置errno
buffer : 发送缓冲区首地址
length : 发送的字节数
flags : 接收方式(通常为0)
(11)套接字关闭
int close(int sockfd);
int shutdown(int sockfd, int howto);
close是双向通信的关闭
TCP连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个方向,这个时候我们可以使用shutdown。针对不同的howto,系统回采取不同的关闭方式。 howto = 0 关闭读通道,但是可以继续往套接字写数据。 howto = 1 和上面相反,关闭写通道。只能从套接字读取数据。 howto = 2 关闭读写通道,和close()一样
二。实验:WiFi UDP Clinet编程
1.功能分析
完成UDP Client功能开发
(1)PC模拟UDP Server,指定(IP,PORT),等待Client数据
(2)UDP Client向Sever发送“I am Client!”
(3)Sever收到数据后,向Client发送“I am Server!”
2.功能实现
(1)在SDK目录下新建udpclient目录
(2)拷贝Station目录下所有文件到udpclient目录下
(3)在user目录下新建udpclient.c
(4)在include目录下新建udpclient.h
(1)Sourceinsight配置
在之前的工程中,移除AP文件夹 添加udpclient文件夹
添加lwip文件夹
同步:
发现的问题:
QQ的截屏比SourceInsight复制优先级低,即先复制代码,在截屏之后粘贴还是复制的代码
3.代码实现
1.在udpclient.c下,添加《整体复制粘贴》
(1)udpclient初始化
(2)udpclient任务
#include "esp_common.h"#include "freertos/FreeRTOS.h" #include "freertos/task.h"#include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" #include "udpclient.h"#define SERVERADDR "192.168.3.12"//注意:这是wifi分配的ip地址,会变化 #define SERVERPORT 8000 /******************************************************************************* FunctionName : ATaskUdpClient* Description : ATaskUdpClient 任务* Parameters : none* Returns : none *******************************************************************************/ void ATaskUdpClient( void *pvParameters ) {int iVariableExample = 0;int fd = -1;int NetTimeOnt = 5000;int ret;struct sockaddr_in ServerAddr;char udpmsg[48];STATION_STATUS StaStatus;do {StaStatus = wifi_station_get_connect_status();vTaskDelay(100);}while(StaStatus != STATION_GOT_IP);fd = socket(PF_INET,SOCK_DGRAM,0);if(fd == -1){printf("get socket fail!\n");vTaskDelete(NULL);}setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&NetTimeOnt,sizeof(int));memset(&ServerAddr,0,sizeof(ServerAddr));ServerAddr.sin_family = AF_INET;ServerAddr.sin_addr.s_addr = inet_addr(SERVERADDR);ServerAddr.sin_port = htons(SERVERPORT);ServerAddr.sin_len = sizeof(ServerAddr);for(;;){sendto(fd,"I am UdpClient!",sizeof("I am UdpClient!"),0,(struct sockaddr *)&ServerAddr,(socklen_t)ServerAddr.sin_len);do{ret = recvfrom(fd,udpmsg,48,0,(struct sockaddr *)&ServerAddr,(socklen_t*)(&ServerAddr.sin_len));if(ret > 0){printf("UdpServer:%s\n",udpmsg);}else{printf("UdpServer data is no!\n");}}while(ret == -1);}vTaskDelete( NULL ); } /******************************************************************************* FunctionName : UdpClient_init* Description : UdpClient_init 初始化* Parameters : none* Returns : none *******************************************************************************/ void UdpClient_init(void) {xTaskCreate(ATaskUdpClient, "UdpClient", 256, NULL, 4, NULL); }注意:上述的IPv设置的是本机的IP地址
Win+R---》cmd进入命令行
输入ipconfig查询无线网络ipv4地址
对上述代码的解释
<1>判断是否获取到IP地址
<2>创建socket
<3>设置接收超时时间
<4>赋值server信息
<5>发送数据到server端
<6>从server端接收数据
2.在udpclient.h下声明《整体复制》
#ifndef __UART_H__ #define __UART_H__#ifdef __cplusplus extern "C" { #endifvoid ATaskUdpClient( void *pvParameters ); void UdpClient_init(void);#ifdef __cplusplus } #endif#endif3.在user_main中
UdpClient_init();
5.运行方式
(1)创建一个UDP,ip为本机被分配的无线ipv4地址,端口为程序代码设置的端口
查询IP地址(通过ipconfig命令获取本机ip地址)
(2)建立串口通讯,波特率为74880,关闭RTS,使用终端模式
4.结果
(1)串口中打印从UDP服务器传输过来的数据(123)
三。实验:WiFi UDP Server编程
1.功能分析
实验要求:
完成UDP Server功能开发1.PC模拟UDP Client,指定UDP Server (IP,PORT),发送“I am Client!”
2.Sever收到数据后,向Client发送“I am Server!”
2.功能实现
新建udpserver工程目录
1.在SDK目录下新建udpserver目录
2.拷贝udpclient目录下所有文件到udpserver目录下
新建udpserver源码文件
1.在user目录下新建udpserver.c
2.在include目录下新建udpserver.h
Sourceinsight配置
1.在之前的工程中,移除udpclient文件夹
2.添加udpserver文件夹
3.代码实现
1.复制之前udpclient代码到udpserver上,进行修改
(1)重命名UdpClient_init为UdpServer_init
(2)重命名ATaskUdpClient为ATaskUdpServer
2.修改user_main.c
(1)包涵udpserver.h
(2)在user_init里修改为UdpServer_init
代码的详细解释
1.判断是否获取到IP地址
2.创建socket
3.Serveraddr 信息设置
4.设置接收超时时间
5.绑定socket
6.从Client端接收数据
7.发送数据到Client端
结果:
四。WiFi TCP Client编程
1.功能分析
实验要求:
完成TCP Client功能开发
1.PC模拟TCP Server,指定(IP,PORT),等待Client数据
2.TCP Client向Sever发送“I am Client!”
3.Sever收到数据后,向Client发送“I am Server!”
2.功能实现
新建tcpclient工程目录
1.在SDK目录下新建tcpclient目录
2.拷贝udpclient目录下所有文件到tcpclient目录下
新建tcpclient源码文件
1.在user目录下新建tcpclient.c
2.在include目录下新建tcpclient.h
Sourceinsight配置
1.在之前的工程中,移除udpserver文件夹
2.添加tcpclient文件夹
3.代码实现
1.复制之前udpclient代码到tcpclient上,进行修改
(1)重命名UdpClient_init为TcpClient_init
(2)重命名ATaskUdpClient为ATaskTcpClient
2.修改user_main.c
(1)包涵tcpclient.h
(2)在user_init里修改为TcpClient_init
代码详细解释
1.判断是否获取到IP地址
2.创建socket
3.设置接收超时时间
4.赋值server信息
5.连接到server端
6.发送数据到server端
7.从server端接收数据
五。实验:WiFi TCP Server编程
1.功能分析
实验要求:
完成TCP Server功能开发
1.PC模拟TCP Client,指定Server(IP,PORT)
(1)进行连接,连接成功后发生“I am Client!”
(2)Sever收到数据后,向Client发送“I am Server!”
2.功能实现
新建tcpserver工程目录
1.在SDK目录下新建tcpserver目录
2.拷贝tcpclient目录下所有文件到tcpserver目录下
新建tcpserver源码文件
1.在user目录下新建tcpserver.c
2.在include目录下新建tcpserver.h
Sourceinsight配置
1.在之前的工程中,移除tcpclient文件夹
2.添加tcpserver文件夹
3.代码实现
1.复制之前tcpclient代码到tcpserver上,进行修改
(1)重命名TcpClient_init为TcpServer_init
(2)重命名ATaskTcpClient为ATaskTcpServer
2.修改user_main.c
(1)包涵tcpserver.h
(2)在user_init里修改为TcpServer_init
代码详解
1.判断是否获取到IP地址
2.创建socket
3.设置接收超时时间
4.赋值server信息
5.绑定socket
6.监听socket
7.处理Client 连接
8.接收Client 数据
9.发送数据到Server
10.关闭socket
相关文章:
3.wifi开发,网络编程
网络协议栈LwIP WiFi UDP Clinet编程 WiFi UDP Server编程 WiFi TCP Client编程 WiFi TCP Server编程 一。LWIP原理介绍,API介绍,文件结构 1.Lwip支持的协议 2.API 3.文件结构 1.api目录:应用程序接口文件。 2.arch目录:与硬件和…...
Android框架mqtt库无法兼容高版本android13的问题
最近使用mqtt库,测试的时候发现在Android12及以下正常,但在13上闪退,闪退日志如下 java.lang.IllegalArgumentException: com.yummo.xcar: Targeting S (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be spe…...
一招解除csdn复制限制
先看这个代码 python读取英文pdf翻译成中文pdf文件导出代码 想要复制代码,csdn有限制怎么办(csdn流氓,无耻) 解除方法 ctrlu 看效果...
安全基础 --- nodejs沙箱逃逸
nodejs沙箱逃逸 沙箱绕过原理:沙箱内部找到一个沙箱外部的对象,借助这个对象内的属性即可获得沙箱外的函数,进而绕过沙箱 前提:使用vm模块,实现沙箱逃逸环境。(vm模式是nodejs中内置的模块,是no…...
Redis集群架构搭建——主从、哨兵、集群
上一篇文章Ubuntu上通过源码方式安装Redis已经介绍了如何安装redis,在这篇文章中,将会教大家搭建Redis的几种高可用的架构:主从架构、哨兵集群、Cluster集群。 本篇文章使用的redis版本为6.2.13,不同版本的配置可能有略微的区别&a…...
39 | selenium基础架构,UI测试架构
什么是测试基础架构? 测试基础架构指的是,执行测试的过程中用到的所有基础硬件设施以及相关的软件设施。因此,我们也把测试基础架构称之为广义的测试执行环境。通常来讲,测试基础架构主要包括以下内容: 执行测试的机器…...
2023研究生数学建模E题保姆级思路 出血性脑卒中临床智能诊疗
本次E题是一道J机器学习题目,难度也比较高,该题一般是有正确结果的,容易踩坑,不太建议小白选择,小白可以选择D题,D题思路也可以看另一篇文章,总的难度都不算低,这三道的难度接近&…...
画电路板通用知识
快捷键 快捷键 功能 shift+鼠标滚轮左右移动Ctrl+鼠标滚轮放大缩小 (Alt+) 鼠标滚轮上下移动滚轮按下鼠标滚轮可任意方向拖动图纸(可以一直保持按下状态或者按一下松开) CTRL+鼠标左键拖动复制该元件CTRL+E编辑选中元件的属性CTRL+鼠标左键 元叠选izoom in,聚焦光标所…...
三相组合式过电压保护器试验
三相组合式过电压保护器试验 试验目的 三相组合式过电压保护器主要分为有带串联间隙过压保护器和无间隙过压保护器两大类,其试验项目内容要求分别使用高压工频交流和高压直流电源。 三相组合式过电压保护器试验,主要是为了及早发现设备内部绝缘受潮及…...
C++提高编程:01 模板
这里写目录标题 1 模板的概念2 函数模板2.1 函数模板语法2.2 函数模板注意事项2.3 函数模板案例2.4 普通函数与函数模板的区别2.5 普通函数与函数模板的调用规则2.6 模板的局限性 3 类模板3.1 类模板语法3.2 类模板与函数模板区别3.3 类模板中成员函数创建时机3.4 类模板对象做…...
Latex Overleaf 写作问题记录
Latex & Overleaf 写作问题记录 公式换行及排列整齐 \begin{equation} \begin{split}Y & a1\\&b2 \end{split} \end{equation}顶格 \noindent求和符号 求和符号(上下限上下排列) \sum\limlits求和符号(上下限右边排列&#…...
OpengL之纹理
简介 我们可以为每个顶点添加颜色来增加图形的细节,从而创建出有趣的图像。但是,如果想让图形看起来更真实,我们就必须有足够多的顶点,从而指定足够多的颜色。这将会产生很多额外开销,因为每个模型都会需求更多的顶点…...
IOTE 2023盛况回顾,美格智能聚连接之力促数字新生长
9月20~22日,IOTE国际物联网展深圳站在深圳国际会展中心正式召开。本届展会以“IoT构建数字经济底座”为主题,聚焦物联网技术助推数字经济发展的核心动力。美格智能携前沿技术成果亮相展会,与参展观众深入交流。 展会上,美格智能带…...
科普:什么是视频监控平台?如何应用在场景中?
随着科技的发展,监控无处不在,就像一张密不透风的网,将生活中的角角落落都编织在一起。可是,你真的知道什么是安防视频监控平台吗?它可不止是一个简单的通电摄像头,如今的视频监控平台,涵盖了无…...
arcgis js 缓冲区分析(GP服务)
arcgis文档中的有提供缓冲区的接口 geometryService,但要4.19后版本才提供 案例中使用的版本为4.16,因此这里的缓冲区分析借助gp工具 新建服务 1、打开arcmap 选择工具将要存放的文件夹,右键> new > Toolbox 对新建好的工具的mode…...
【word格式】mathtype公式插入 | 段落嵌入后格式对齐 | 字体大小调整 |空心字体
1. 公式嵌入 推荐在线latex编辑器,可以截图转 latex 识别率很高 https://www.latexlive.com/home 美中不足,不开会员每天只能用3次识别。 通过公式识别后,输出选择align环境,然后在mathtype中直接粘贴latex就可以转好。 2.公式…...
【动态规划刷题 17】回文子串 最长回文子串
647. 回文子串 链接: 647. 回文子串 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串,即使是由…...
mysql 每日自动备份数据库
在 MySQL 中,你可以使用定时任务来每日自动备份数据库。通常,最常用的方法是使用操作系统的定时任务工具(如cron)来调度备份操作。以下是一些步骤来设置每日定时备份MySQL数据库: 创建备份脚本:首先&#x…...
【计算机网络】图解路由器(二)
本系列包含: 图解路由器(一)图解路由器(二) 图解路由器(二) 21、什么是静态路由?22、什么是动态路由?23、动态路由有哪些类型?24、什么是 RIP ?2…...
流媒体及直播相关知识
文章目录 前言一、流媒体1、基本概念2、流式传输3、流媒体技术原理4、流媒体传输模式5、H.264 流媒体传输系统框架 二、直播1、直播中使用的流媒体协议2、直播的模块划分3、视频直播流程①、推流到服务器②、服务器流分发 前言 本文主要讲解流媒体及其直播相关知识,…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...
2025 后端自学UNIAPP【项目实战:旅游项目】7、景点详情页面【完结】
1、获取景点详情的请求【my_api.js】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http(/login/getWXSessionKey, {code,avatar}); };//…...

















