stm32实现esp8266连接到TCP服务器(二)未完

1.2 连接到TCP Server

                1.2.1 使用网络助手,设立TCP服务器

编辑

                1.2.2 连接服务器

AT+CIPSTART="TCP","192.168.1.18",8080 //指令,注意双引号逗号都要半角(英文)输入 CONNECT //结果:成功 OK //结果:成功
OK

                1.2.3 发送数据

AT+CIPSEND=4 //设置即将发送数据的长度

>abcd        //看到大于号后,输入消息,abcd,不要带回车

Response :SEND OK //结果:成功

//注意,这种情况下,每次发送前都要线发送AT+CIPSEND=长度,的指令,在发数据!

1.3 透传

用AT + CIPSEND = 4,每次发送数据都要进行字符长度设定

今天透传模式

AT+CIPMODE=1 //开启透传模式

Response :OK

AT+CIPSEND //带回车

Response: > //这个时候随意发送接收数据咯

退出透传模式

 在透传发送数据过程中,若识别到单独的⼀包数据 “+++”,则退出透传发送

头文件

#include "sys.h"
#include "esp8266.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"
uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE];
uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE]; uint16_t esp8266_cnt = 0 ,esp8266_cntPre = 0; /* esp8266接收缓冲区 */UART_HandleTypeDef esp8266_handle;             /* esp8266句柄 */

esp8266模块串口配置初始化

//正常会有启动的流程只是作为一个串口的初始化
void esp8266_uart_init(uint16_t baudrate)
{esp8266_handle.Instance = USART2;                  /* USART1 */esp8266_handle.Init.Baudrate = baudrate;           /*波特率*/esp8266_handle.Init.WordLength= UART_WORDLENGTH_8B;/*字长为8位的数据格式传输*/esp8266_handle.Init.StopBits = UART_STOPBITS_1;    /*一个停止位*/ esp8266_handle.Init.Parity   = UART_PARITY_NONE;                   /*无奇偶校验位*/esp8266_handle.Init.HwFlowCtl = UART_HWCONTRL_NONE;/*无硬件流控制*/esp8266_handle.Init.Mode      = UART_MODE_TX_RX;   /*收发模式*/HAL_UART_Init(esp8266_handle);
}

清除接收缓存

void esp8266_rx_clear(void)
{memset(esp8266_rx_buf,0,sizeof(esp8266_rx_buf));esp8266_cnt = 0;
}

中断服务函数

void USART2_IRQHandler(void)
{uint8_t receive_data = 0;/* 获取接收RXNE标志位是否被置位 */if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_RXNE) !=RESET){/* 则将接收计数器清零 */if(esp8266_cnt >=sizeof(esp8266_rx_buf))esp8266_cnt = 0;/* 接收一个字符 */HAL_UART_Receive(&esp8266_handle,&receive_data, 1,1000);/* 将接收到的字符保存在接收缓冲区 */esp8266_rx_buf[esp8266_cnt++] = receive_data;
}/* 获取接收空闲中断标志位是否被置位 */if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_IDLE) != RESET){/* 将接收到的数据打印出来 */printf("recv: %s\r\n", esp8266_rx_buf);esp8266_rx_clear();      /* 清除UART总线空闲中断 */__HAL_UART_CLEAR_IDLEFLAG(&esp8266_handle)
}
}

接收等待

uint8_t esp8266_wait_receive(void)
{if(esp8266_cnt == 0)return ESP8266_ERROR;if(esp8266_cnt == esp8266_cntPre){esp8266_cnt = 0;return ESP8266_EOK;}esp8266_cntPre = esp8266_cnt;return ESP8266_ERROR;
}

发送命令与期待回复函数

uint8_t esp8266_send_command(char *cmd,cahr *res)
{uint8_t timeout_out = 250;esp8266_rx_clear();//防止缓冲区内的数据影响HAL__UART_Tramsmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100);while(timeout_out--)//不停的等待{if(esp8266_wait_receive() == ESP8266_EOK){if(strstr(const char *)esp8266_rx_buf, res) != NULL)//判断是否又有期待的字符串return ESP8266_EOK
}return ESP8266_ERROR;
}
}

接收数据

void esp8266_receiv_data(void)
{if(esp8266_wait_receive() = ESP8266_EOK){printf("esp8266 recv: %s\r\n",esp8266_rx_buf);esp8266_rx_clear();}
}

发送不定长数据

void esp8266_send_data(char *fmt, ...)
{va_list ap;uint16_len;va_start(ap,fmt);vsprintf((char *)esp8266_tx_buf,fmt,ap);va_end(ap);len = strlen((const char*)esp8266_tx_buf);HAL__UART_Transmit(&esp8266_handle,esp8266_tx_buf,len,100);// 发送
}

at测试指令

uint8_t esp8266_at_test(void)
{return esp8266_send_command("AT\r\n", "OK");//记得加回车
}

模式设置函数封装

uint8_t esp8266_set_mode(uint8_t mode)
{switch(mode)
{case ESP8266_STA_MODE:return esp8266_send_command("AT+CWMODE=1\r\n");case ESP8266_AP_MODE:return esp8266_send_command("AT+CWMODE=2\r\n");case ESP8266_STA_AP_MODE:return esp8266_send_command("AT+CWMODE=3\r\n");default:return esp8266_EINVL; 
}
}

加入服务器输入账号密码

uint8_t esp8266_join_ap(char *ssid,char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pwd);//作为模式传输进入return esp8266_send_command(cmd."OK");
}

设置单路连接的esp8266连接模式

/*设置单路连接的模式(透传只能用此模式)*/
uint8_t esp8266_connect_mode(uint8_t mode)
{char cmd[64];sprintf(cmd,"AT+CIPMUX=%d\r\n",mode);return esp8266_send_command(cmd,"OK");//发送cmd指令期待回复OK
}

连接tcp服务器

uint8_t esp8266_connect_tcp_sever(char *server_ip,char *server port)
{char cmd[64];sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",server_ip,server_port);return esp8266_send_command,"CONNECT");
}

进入透传模式

uint8_t esp8266_enter_unvarnished(void)//进入透传模式
{uint8_t ret;ret  =  esp8266_send_command("AT+CIPMODE=1\r\n","OK");ret +=  esp8266_send_command("AT+CIPSEND\r\n",">");//调用指令函数if(ret == ESP8266_EOK)return ESP8266_EOK;elsereturn ESP8266_ERROR;
}

esp8266初始化

uint8_t esp8266_init(uint32_t baudrate)
{printf("esp8266初始化开始...\r\n");    esp8266_init_uart(baudrate);printf("1. 测试esp8266是否存在\r\n")while(esp8266_at_test())delay_ms(500);printf("2. 设置工作模式为STA...\r\n");while(esp8266_set_mode(ESP8266_STA_MODE)delay_ms(500);printf("3. 设置单路链接模式\r\n");while(esp8266_connect_mode(ESP8266_SINGLE_CONNECTION))delay_ms(500);printf("4. 连接wifi,SSID: %s ,PWD:%s\r\n",WIFI_SSID,WIFI_PWD);while(esp8266_join_ap(WIFI_SSID,WIFI,PWD))delay_ms(1500);//时间长一些printf("6. 进入透传模式...\r\n");while(esp8266_enter_unvarnished())delay_ms(500);print("esp8266已经连接上tcp服务器并进入透传模式")
}

测试函数

void esp8266_test(void)
{esp8266_send_data("this is from esp8266\r\n");esp8266_receiv_data();
}

main函数

#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "esp8266.h"
int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */led_init();	/* LED初始化 */uart1_init(115200);esp8266_init(115200);printf("helloworld!\r\n");		while(1){       			esp8266_test();delay_ms(500);}
}

2. ESP8266作为服务器

USB转TTL插入电脑,TX--RX RX-TX VCC-3.3V GND-GND

查询IP地址:AT+CIFSR

//1 配置成AP模式

AT+CWMODE=2

Response :OK

//2 使能多链接

AT+CIPMUX=1 Response :OK

//3 建立TCPServer

AT+CIPSERVER=1 // default port = 333 Response :OK

//4 发送数据

AT+CIPSEND=0,4      // 发送4个字节在连接0通道上 >abcd//输入数据,

Response :SEND OK //不带回车

//5 接收数据

+IPD, 0, n: xxxxxxxxxx //+IPD是固定字符串 0是通道,n是数据长度,xxx是数据

//断开连接

AT+CIPCLOSE=0

Response :0, CLOSED OK

 头文件

#include "sys.h"
#include "esp8266.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE];
uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE]; uint16_t esp8266_cnt = 0 ,esp8266_cntPre = 0; /* esp8266接收缓冲区 */UART_HandleTypeDef esp8266_handle;             /* esp8266句柄 */

esp8266串口初始化配置

void esp8266_uart_init(uint32_t baudrate)//正常会有启动的流程只是作为一个串口的初始化
{/*esp8266 初始化设置*/esp8266_handle.Instance = USART2;                               /* USART1 */esp8266_handle.Init.BaudRate = baudrate;                        /* 波特率 */esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B;            /* 字长为8位数据格式*/esp8266_handle.Init.StopBits = UART_STOPBITS_1;                 /* 一个停止位 */esp8266_handle.Init.Parity = UART_PARITY_NONE;                  /* 无奇偶校验位 */esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;            /* 无硬件流控 */esp8266_handle.Init.Mode = UART_MODE_TX_RX;                     /* 收发模式 */HAL_UART_Init(&esp8266_handle);                                 /*会使能esp8266 */                 
}

接收缓冲区配置

void esp8266_rx_clear(void)
{memset(esp8266_rx_buf, 0, sizeof(esp8266_rx_buf)); /* 清空接收缓冲区 */esp8266_cnt = 0;                                   /* 接收计数器清零 */
}

中断服务函数

void USART2_IRQHandler(void)
{uint8_t receive_data = 0;   if(__HAL_UART_GET_FLAG(&esp8266_handle, UART_FLAG_RXNE) != RESET){/* 获取接收RXNE标志位是否被置位 */if(esp8266_cnt >= sizeof(esp8266_rx_buf))                     /* 如果接收的字符数大于接收缓冲区大小, */esp8266_cnt = 0;                                          /* 则将接收计数器清零 */HAL_UART_Receive(&esp8266_handle, &receive_data, 1, 1000);    /* 接收一个字符 */esp8266_rx_buf[esp8266_cnt++] = receive_data;    /* 将接收到的字符保存在接收缓冲区 */}if (__HAL_UART_GET_FLAG(&esp8266_handle, UART_FLAG_IDLE) != RESET) /* 获取接收空闲中断标志位是否被置位 */{printf("recv: %s\r\n", esp8266_rx_buf);                  /* 将接收到的数据打印出来 */esp8266_rx_clear();__HAL_UART_CLEAR_IDLEFLAG(&esp8266_handle);              /* 清除UART总线空闲中断 */}
}

等待接收函数

uint8_t esp8266_wait_receive(void)
{if(esp8266_cnt == 0)return ESP8266_ERROR;if(esp8266_cnt == esp8266_cntPre){esp8266_cnt = 0;return ESP8266_EOK;}esp8266_cntPre = esp8266_cnt;return ESP8266_ERROR;
}

发送指令并期待返回值

uint8_t esp8266_send_command(char *cmd,char *res)//发送一个指令去   在指定时间内返回回来 否则没有接收到一个返回值
{uint8_t timeout_out = 250;esp8266_rx_clear(); //防止忍心内的数据影响HAL_UART_Transmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100);//发送命令 cmd在这里是一个uint8_t的数据 长度 阻塞的值//等待while(timeout_out--)//不停的等待{if(esp8266_wait_receive() == ESP8266_EOK){if(strstr((const char*)esp8266_rx_buf, res) != NULL)//判断是否又有期待的字符串return ESP8266_EOK;}delay_ms(10);}return ESP8266_ERROR;//否则接收错误}

接收数据

//接收的函数
void esp8266_receiv_data(void)
{if(esp8266_wait_receive() == ESP8266_EOK){printf("esp8266 recv: %s\r\n", esp8266_rx_buf);esp8266_rx_clear();}
}

发送不定长数据

//发送的函数  不定长数据 参数不固定
void esp8266_send_data(char *fmt, ...)
{va_list ap;uint16_t len;va_start(ap,fmt);vsprintf((char *)esp8266_tx_buf,fmt, ap);va_end(ap);len = strlen((const char*)esp8266_tx_buf);HAL_UART_Transmit(&esp8266_handle, esp8266_tx_buf, len,100);//发送
}

设置a模块是否存在测试

uint8_t esp8266_at_test(void)
{return esp8266_send_command("AT\r\n", "OK");//记得加回车换行才能作为指令发送期待返回值为OK  直接作为返回值发送}

设置模式

uint8_t esp8266_set_mode(uint8_t mode)//s四个函数
{switch(mode){case ESP8266_STA_MODE:return esp8266_send_command("AT+CWMODE=1\r\n","OK");case ESP8266_AP_MODE:return esp8266_send_command("AT+CWMODE=2\r\n","OK");case ESP8266_STA_AP_MODE:return esp8266_send_command("AT+CWMODE=3\r\n","OK");default:return ESP8266_EINVAL;//如果指令不存在}
}

加入AP


uint8_t esp8266_join_ap(char *ssid,char *pwd)//账号密码
{char cmd[64];sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pwd);//\"HUAWEIAP-1\",=\"%s\  就指令带引号直接写不行,我们需要如此就不会将“”认为是配对的return esp8266_send_command(cmd,"WIFI GOT IP");;//调用指令函数
}

连接模式

	
uint8_t esp8266_connect_mode(uint8_t mode)//设置单路连接的模式(透传只能用此模式)
{char cmd[64];sprintf(cmd, "AT+CIPMUX=%d\r\n",mode);//作为模式传输进入return esp8266_send_command(cmd,"OK");;//调用指令函数
}
//连接TCP服务器

esp8266_连接模式

uint8_t esp8266_connect_mode(uint8_t mode)//设置单路连接的模式(透传只能用此模式)
{char cmd[64];sprintf(cmd, "AT+CIPMUX=%d\r\n",mode);//作为模式传输进入return esp8266_send_command(cmd,"OK");;//调用指令函数
}

 esp8266连接tpc服务器ip和端口

uint8_t esp8266_connect_tcp_server(char *server_ip,char*server_port)
{char cmd[64];sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",server_ip,server_port);//作为模式传输进入return esp8266_send_command(cmd,"CONNECT");;//调用指令函数
}

进入透传模式

uint8_t esp8266_enter_unvarnished(void)//发送的模式
{uint8_t ret;//取巧的方式定义一个返回值//两次返回值都等于0,如果有一个不为0就为不为零的情况ret  = esp8266_send_command("AT+CIPMODE=1\r\n","OK");;//调用指令函数ret += esp8266_send_command("AT+CIPSEND\r\n",">");;//调用指令函数if(ret == ESP8266_EOK)return ESP8266_EOK;elsereturn ESP8266_ERROR;		
}

建立tcp服务器

uint8_t esp8266_build_tcp_server(void)
{return esp8266_send_command("AT+CIPSERVER=1\r\n","OK");//发送AT+CIPSEVER=1,期待回复OK
}

初始化esp8266


void esp8266_init(uint32_t baudrate)//所以增加新添加一个
{printf("esp8266初始化开始...\r\n");esp8266_uart_init(baudrate);printf("1. 测试esp8266是否存在\r\n");while(esp8266_at_test())//esp8266_at_test();也是可以的不过一直不成功那就一直等待更为保险delay_ms(500);printf("2. 设置工作模式为AP...\r\n");while(esp8266_set_mode(ESP8266_AP_MODE))delay_ms(500);printf("3. 设置多路链接模式\r\n");while(esp8266_connect_mode(ESP8266_MULTI_CONNECTION))delay_ms(500);printf("4. 建立TCP服务器...\r\n");while(esp8266_build_tcp_server())delay_ms(500);		printf("esp8266初始化完成...\r\n");//esp8266的其他初始化
}

esp8266初始化测试

//测试函数
void esp8266_test(void)
{esp8266_send_data("this is from esp8266\r\n");esp8266_receiv_data();
}

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

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

相关文章

jmeter中用csv data set config做参数化2

在jmeter中,使用csv data set config进行参数化是很重要的一个功能,但是这个功能的使用需要十分仔细和小心,因为细节之处往往决定着结果的正确与否。 举例: 一个登录接口用加密密码登录,一个登录接口用原始密码登录。…

STM32G4系列MCU的低功耗模式介绍

目录 概述 1 认识低功耗模式 1.1 低功耗模式的应用 1.2 低功耗模式介绍 2 低功耗模式的状态关系 2.1 低功耗模式可能的转换状态图 2.2 低功耗模式总结 3 运行模式 3.1 减慢系统时钟 3.2 外围时钟门控 3.3 低功耗运行模式(LP运行) 概述 本文主…

JavaFx学习--chapter02(网络对话)

chapter02(网络对话) 简单网络对话程序 设计任务:客户端向服务器发送字符串,并能读取服务器返回的字符串。 知识点:TCP套接字技术,C/S软件架构程序设计 重点理解:Java客户套接字类Socket和服务器套接字类ServerSoc…

蜜罐技术的出现究竟影响了什么

自网络诞生以来,攻击威胁事件层出不穷,网络攻防对抗已成为信息时代背景下的无硝烟战争。然而,传统的网络防御技术如防火墙、入侵检测技术等都是一种敌暗我明的被动防御,难以有效应对攻击者随时随地发起的无处不在的攻击和威胁。蜜…

linux线程 | 同步与互斥 | 互斥(下)

前言:本篇文章主要讲述linux线程的互斥的知识。 讲解流程为先讲解锁的工作原理, 再自己封装一下锁并且使用一下。 做完这些就要输出一堆理论性的东西, 但博主会总结两条结论!!最后就是讲一下死锁。 那么, 废…

什么是 Idempotence 以及它在哪里使用?

大家好,我是锋哥。今天分享关于【什么是 Idempotence 以及它在哪里使用?】面试题?希望对大家有帮助; 什么是 Idempotence 以及它在哪里使用? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Idempotence&am…

【C++STL】list的基本介绍与使用方式

✨ Blog’s 主页: 白乐天_ξ( ✿>◡❛) 🌈 个人Motto:他强任他强,清风拂山冈! 🔥 所属专栏:C深入学习笔记 💫 欢迎来到我的学习笔记! 一、list的介绍 文档内容以及大致翻…

ESP32-IDF 非易失存储 NVS

目录 零、前言一、基本介绍1、配置结构体1.1 nvs_entry_info_t 2、常用 API2.1 nvs_flash_init2.2 nvs_flash_init_partition2.3 nvs_flash_init_partition_ptr2.4 nvs_flash_erase2.5 nvs_flash_erase_partition2.6 nvs_flash_erase_partition_ptr2.7 nvs_flash_generate_keys…

element plus中menu菜单技巧

我在使用element plus的menu(侧边栏)组件的过程中遇到了一些问题,就是menu编写样式和路由跳转,下面给大家分享以下,我是怎么解决的。 1.页面效果 我要实现的网站布局是这样的: 侧边栏折叠以后的效果&#…

python爬虫快速入门之---Scrapy 从入门到包吃包住

python爬虫快速入门之—Scrapy 从入门到包吃包住 文章目录 python爬虫快速入门之---Scrapy 从入门到包吃包住一、scrapy简介1.1、scrapy是什么?1.2、Scrapy 的特点1.3、Scrapy 的主要组件1.4、Scrapy 工作流程1.5、scrapy的安装 二、scrapy项目快速入门2.1、scrapy项目快速创建…

详解equals底层原理

equals 方法是 Java 中用于比较两个对象是否“相等”的方法。在 Java 中,每个类都继承自 java.lang.Object 类,而 equals 方法正是定义在 Object 类中的一个方法。默认情况下,Object 类的 equals 方法比较的是两个对象的内存地址(…

SQL 多表联查

SQL JOIN (w3school.com.cn) SQL join用于根据两个或多个表中的列之间的关系,从这些表中查询数据。 之前跟着老师学数据库的时候学过,最近又在比较频繁的使用,再复习一下。 Person表: Id_P :居民编号。主键 …

大数据开发基于Hadoop+springboot平台的岗位推荐系统

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图文章目录 前言 文章底部名片,获取项目的完整演示视频,免费解答技术疑问 项目介绍 随着网络科学技术不断的发展和普及化,用户在寻找适合自己的信息管理系统时面临着越来…

成功解决pycharm软件中按住Ctrl+点击指定函数却不能跳转到对应库中的源代码

成功解决pycharm软件中按住Ctrl点击指定函数却不能跳转到对应库中的源代码 目录 解决问题 解决方法 解决问题 在pycharm软件中按住Ctrl点击指定函数却不能跳转到对应库中的源代码 解决方法

探索秘境:如何使用智能体插件打造专属的小众旅游助手『小众旅游探险家』

文章目录 摘要引言智能体介绍和亮点展示介绍亮点展示 已发布智能体运行效果智能体创意想法创意想法创意实现路径拆解 如何制作智能体可能会遇到的几个问题快速调优指南总结未来展望 摘要 本文将详细介绍如何使用智能体平台开发一款名为“小众旅游探险家”的旅游智能体。通过这…

个人健康系统|个人健康数据管理系统|基于小程序+java的个人健康数据管理系统设计与实现(源码+数据库+文档)

个人健康数据管理系统 目录 基于小程序java的个人健康数据管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师…

重构案例:将纯HTML/JS项目迁移到Webpack

我们已经了解了许多关于 Webpack 的知识,但要完全熟练掌握它并非易事。一个很好的学习方法是通过实际项目练习。当我们对 Webpack 的配置有了足够的理解后,就可以尝试重构一些项目。本次我选择了一个纯HTML/JS的PC项目进行重构,项目位于 GitH…

web3学习-区块链基础知识

1.1 区块链技术简史 block chain 点对点的分布式交易系统 比特币协议并不是图灵完备的。 以太坊协议加入了智能合约,智能合约是以太坊协议与比特币协议的最大区别(图灵完备) 1.2、区块链设计哲学 去中心化 由于没有中心化的数据库作为…

记录一个容易混淆的 Spring Boot 项目配置文件问题

记录一个容易混淆的 Spring Boot 项目配置文件问题 去年,我遇到了这样一个问题: 在这个例子中,由于密码 password 以 0 开头,当它被 Spring Boot 的 bean 读取时,前导的 0 被自动去掉了。这导致程序无法正确读取密码。…

网盘直链下载神器NDM

工具介绍 ​Neat Download Manager分享一款网盘不限速神器,安装步骤稍微有一点繁琐,但实际体验下载速度飞快,个人实际体验还是非常不错的 NDM是一款免费且强大的下载工具。可以帮助你下载各种文件,还能够在多任务下载中保持出色的速度及其稳定性 通过网盘分享的文…