HTTP简介
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
HTTP工作原理
HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
Web服务器有:Apache服务器,IIS服务器(Internet Information Services)等。
Web服务器根据接收到的请求后,向客户端发送响应信息。
HTTP默认端口号为80,但是你也可以改为8080或者其他端口。
HTTP三点注意事项:
- **HTTP是无连接:**无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- **HTTP是媒体独立的:**这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
- **HTTP是无状态:**HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
具体实现过程
- 通常要使用HTTP请求都是先建立起TCP/IP的连接,与服务器建立TCP通信;
- 发送具体的HTTP请求
- 接收服务器返回的数据
- 关闭连接
当然在ESP8266上实现还需要先让设备能够联网上网,ESP8266-RTOS-SDK提供了对应的wifi连接接口,见 esp_wifi.h 所有的wifi相关接口都在这里,包括切换STA和AP,在ESP8266-RTOS-SDK中,提供了一个适配器的概念,目的是在TCPIP堆栈上提供一个抽象层,据官方文档介绍是为了实现切换到其他TCPIP栈而设计的,具体的我也没研究透,根据文档,只需要在连接wifi前对适配器进行初始化就行;
tcpip_adapter_init();
连接wifi:
**WiFi初始化:esp_err_t esp_wifi_init(const wifi_init_config_t *config) **
例如WiFi控制结构,RX / TX缓冲区,WiFi NVS结构等,此WiFi也会启动WiFi任务。
相关参数结构体:wifi_init_config_t 针对wifi配置的相关结构体
typedef struct {
system_event_handler_t event_handler; /**< WiFi event handler */
void* osi_funcs; /**< WiFi OS functions */
int static_rx_buf_num; /**< WiFi static RX buffer number */
int dynamic_rx_buf_num; /**< WiFi dynamic RX buffer number */
int tx_buf_type; /**< WiFi TX buffer type */
int static_tx_buf_num; /**< WiFi static TX buffer number */
int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */
int csi_enable; /**< WiFi channel state information enable flag */
int ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */
int ampdu_tx_enable; /**< WiFi AMPDU TX feature enable flag */
int nvs_enable; /**< WiFi NVS flash enable flag */
int nano_enable; /**< Nano option for printf/scan family enable flag */
int tx_ba_win; /**< WiFi Block Ack TX window size */
int rx_ba_win; /**< WiFi Block Ack RX window size */
int magic; /**< WiFi init magic number, it should be the last field */
} wifi_init_config_t;
第一次看到这个头都大,所幸官方提供了一个默认的宏配置:
#define WIFI_INIT_CONFIG_DEFAULT() { \
.event_handler = &esp_event_send, \
.osi_funcs = NULL, \
.static_rx_buf_num = 5,\
.dynamic_rx_buf_num = 0,\
.tx_buf_type = 0,\
.static_tx_buf_num = 6,\
.dynamic_tx_buf_num = 0,\
.csi_enable = 0,\
.ampdu_rx_enable = 0,\
.ampdu_tx_enable = 0,\
.nvs_enable = 1,\
.nano_enable = 0,\
.tx_ba_win = 0,\
.rx_ba_win = 0,\
.magic = WIFI_INIT_CONFIG_MAGIC\
};
esp_err_t esp_wifi_deinit( void )
与WiFi初始化相对于的一个函数,用于释放esp_wifi_init中分配的所有资源并停止WiFi任务。
esp_err_t esp_wifi_set_storage(wifi_storage_t storage )
设置WiFi API配置存储类型
typedef enum {
WIFI_STORAGE_FLASH, /**< 所有配置信息都保存在memory和flash中 */
WIFI_STORAGE_RAM, /**< 所有配置信息只保存在memory中 */
} wifi_storage_t;
esp_err_t esp_wifi_set_mode(wifi_mode_t mode);
设置wifi工作模式;
typedef enum {
WIFI_MODE_NULL = 0, /**< null mode */
WIFI_MODE_STA, /**< WiFi station mode */
WIFI_MODE_AP, /**< WiFi soft-AP mode */
WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */
WIFI_MODE_MAX
} wifi_mode_t;
*esp_err_t esp_wifi_set_config(wifi_interface_t , wifi_config_t conf);
设置ESP8266 STA或AP的配置
参数类型 | 解析 |
---|---|
wifi_interface_t | typedef enum { ESP_IF_WIFI_STA = 0, /< ESP8266 station interface */ ESP_IF_WIFI_AP, /< ESP8266 soft-AP interface */ ESP_IF_MAX } esp_interface_t; |
wifi_config_t | typedef union { wifi_ap_config_t ap; /< configuration of AP */ wifi_sta_config_t sta; /< configuration of STA */ } wifi_config_t; |
由于wifi_config_t是一个联合体,在使用的时候我们可以这样,例如使用STA模式:
wifi_config_t wifi_config = { //填入wifi信息
.sta = { //sta模式
.ssid = EXAMPLE_WIFI_SSID, //作为STA需要接入的AP(路由器/WIFI)的ID
.password = EXAMPLE_WIFI_PASS, //(路由器/WIFI)密码
},
};
esp_err_t esp_wifi_start(void);
当所有的配置都做好后,调用该函数会根据当前配置启动WiFi如果模式为WIFI_MODE_STA,则创建站点控制块并启动站点如果模式为WIFI_MODE_AP,则创建软AP控制块并启动soft-AP如果模式为WIFI_MODE_APSTA,则创建软AP和站点控制块并启动软AP和工作站。
让8266在STA模式连接WIFI步骤总结如下:
- 初始化适配器
- 新建一个配置wifi的结构体,然后调用wifi初始化函数
- 设置WiFi API配置存储类型
- 设置WiFi工作模式
- 设置ESP8266 STA或AP的配置
- 启动WiFi
tcpip_adapter_init();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_storage(WIFI_STORAGE_RAM);
wifi_config_t wifi_config = { //填入wifi信息
.sta = { //sta模式
.ssid = EXAMPLE_WIFI_SSID, //wifi名称
.password = EXAMPLE_WIFI_PASS, //wifi密码
},
};
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
esp_wifi_start();
发出http请求
完成前面的联网后,发出http请求就很简单了,
- 创建一个TCP的客户端socket
- 往socket写入具体的HTTP请求
- 接收回发的数据
本文使用的是我之前封装好的一个接口,点击获取,如果对你有用请点个关注或者星标,谢谢
头文件:#include <sys/socket.h>
int socket(int domain, int type, int protocol); //创建socket
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //连接服务器
完了之后就是往socket写入封装好的URL即可
头文件:#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count); //写
ssize_t read(int fd, void *buf, size_t count); //读
本次测试使用的是青云客智能聊天机器人API免费的API,本来是测试获取天气的,但是不知道为什么获取的天气数据中文没法输出,就换成了翻译功能;
#define HEAD_FORMAT "GET /api.php?key=free&appid=0&msg=翻译武汉加油 HTTP/1.1\r\nHost:api.qingyunke.com\r\n\r\n"
效果如图:(天气左边是8266串口输出的,只能显示数字和英文,右边是纯代码测试的输出)
工程源码见我的Github