明珠的个人博客

是谁告诉你,你是赤裸的?

0%

物联网之网络客户端基本操作

网络客户端简介

在我们上网过程中,经常使用网页浏览器来浏览网站信息。在这一场景中,我们的网站浏览器就是一个网络客户端。网络客户端的主要功能就是向服务器发送网络请求。服务器在接收到客户端请求后会将请求的信息回复给客户端。

接下来我们使用ESP8266-NodeMCU开发板扮演网络客户端的角色,从而向网络服务器发送HTTP请求以获取服务器响应信息。

ESP8266-Arduino库中有两个库用于控制ESP8266与网络服务器进行通讯。他们是WiFiClient库和ESP8266HTTPClient库。

这两个库虽然功能相似,但是他们却是截然不同的两个库。ESP8266HTTPClient库相对简单易用。该库的库函数可以自动生成客户端请求信息并解析服务器响应信息。但正是由于该库的库函数为我们做了所有底层工作,这就导致该库不如WiFiclient库灵活。假如我们需要用ESP8266建立自定义客户端请求信息时,就要用WiFiClient库来实现了。另外WiFiClient库在解析服务器响应信息时可以使用丰富的STREAM类函数,这也为我们提供了很多便利。

因此,在我们使用ESP8266开发项目时,更多的时候是使用WiFiClient库来实现物联网通讯功能。换句话说,我个人认为WiFiClient库的重要性和实用性要高于ESP8266HTTPClient库。

以上描述有些抽象,接下来我们看两个简单示例。这两个示例的功能是相同的。都是通过ESP8266通过互联网向网络服务器发送请求并且将将网站服务器响应的信息输出在屏幕中。不同的是,示例一使用了ESP8266HTTPClient库来实现这一操作,示例二使用了WiFiClient库实现。

示例1. 使用ESP8266HTTPClient库实现网络通讯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**********************************************************************
项目名称/Project : 零基础入门学用物联网
程序名称/Program name : HTTPClient_request_basic
团队/Team : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author : Dapenson
日期/Date(YYYYMMDD) : 20200325
程序目的/Purpose :
此程序用于演示如何使用ESP8266来向www.example.com网站服务器发送HTTP请求并通过串口
监视器将网站服务器响应信息通过串口监视器显示出来。
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date 作者/Author 参考号/Ref 修订说明/Revision Description
20200411 CYNO朔 001 将请求服务器改为www.example.com
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
***********************************************************************/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

// 测试HTTP请求用的URL。注意网址前面必须添加"http://"
#define URL "http://www.example.com"

// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "taichimaker";
const char* password = "12345678";

void setup() {
//初始化串口设置
Serial.begin(9600);

//设置ESP8266工作模式为无线终端模式
WiFi.mode(WIFI_STA);

//开始连接wifi
WiFi.begin(ssid, password);

//等待WiFi连接,连接成功打印IP
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi Connected!");

httpClientRequest();
}

void loop() {}

// 发送HTTP请求并且将服务器响应通过串口输出
void httpClientRequest(){

//重点1 创建 HTTPClient 对象
HTTPClient httpClient;

//重点2 通过begin函数配置请求地址。此处也可以不使用端口号和PATH而单纯的
httpClient.begin(URL);
Serial.print("URL: "); Serial.println(URL);

//重点3 通过GET函数启动连接并发送HTTP请求
int httpCode = httpClient.GET();
Serial.print("Send GET request to URL: ");
Serial.println(URL);

//重点4. 如果服务器响应HTTP_CODE_OK(200)则从服务器获取响应体信息并通过串口输出
//如果服务器不响应HTTP_CODE_OK(200)则将服务器响应状态码通过串口输出
if (httpCode == HTTP_CODE_OK) {
// 使用getString函数获取服务器响应体内容
String responsePayload = httpClient.getString();
Serial.println("Server Response Payload: ");
Serial.println(responsePayload);
} else {
Serial.println("Server Respose Code:");
Serial.println(httpCode);
}

//重点5. 关闭ESP8266与服务器连接
httpClient.end();
}

程序重点讲解

重点1. 声明HTTPClient对象,对象名称httpClient。后续程序中,我们将使用对象httpClient控制ESP8266的网络通讯。

重点2. 通过ESP8266HTTPClient库的begin函数来设置ESP8266发送HTTP请求的目标URL。

重点3. 通过ESP8266HTTPClient库的GET函数向服务器发送HTTP请求。

重点4. 以上重点3中GET函数的返回值是网络服务器响应状态码。根据该状态码,我们可以判断服务器是否成功接收到了ESP8266客户端的请求。如果服务器成功接收到请求,我们就可以在接下来使用getString函数来获取服务器响应报文(服务器响应体)信息,并且将该信息传递给responsePayload变量以便我们在后面通过串口监视器显示服务器响应报文。(这一报文信息正是www.example.com网站的首页HTML源代码)。

重点5.执行完以上操作后,我们将关闭ESP8266与服务器连接。这里是通过ESP8266HTTPClient库的end函数来实现这一操作的。

示例2. 使用WiFiClient库实现网络通讯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**********************************************************************
项目名称/Project : 零基础入门学用物联网
程序名称/Program name : wifiClient_request_basic
团队/Team : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author : Dapenson
日期/Date(YYYYMMDD) : 20200325
程序目的/Purpose :
此程序用于演示如何使用esp8266作为互联网客户端向www.example.com网站服务器发送http请求,
并且将网站服务器响应的信息输出在屏幕中
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date 作者/Author 参考号/Ref 修订说明/Revision Description
20200411 CYNO朔 001 将请求服务器改为www.example.com
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
***********************************************************************/
#include <ESP8266WiFi.h>

const char* host = "www.example.com"; // 网络服务器地址
const int httpPort = 80; // http端口80

// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "taichimaker";
const char* password = "12345678";

void setup() {
//初始化串口设置
Serial.begin(9600);
Serial.println("");

//设置ESP8266工作模式为无线终端模式
WiFi.mode(WIFI_STA);

//开始连接wifi
WiFi.begin(ssid, password);

//等待WiFi连接,连接成功打印IP
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected!");

wifiClientRequest();
}

void loop(){}

// 向服务器发送HTTP请求
void wifiClientRequest(){
// 建立WiFi客户端对象,对象名称client
WiFiClient client;

// 建立字符串,用于HTTP请求
String httpRequest = String("GET /") + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n" +
"\r\n";

// 通过串口输出连接服务器名称以便查阅连接服务器的网址
Serial.print("Connecting to ");
Serial.print(host);

// 连接网络服务器,以下段落中的示例程序为本程序重点1
// 请参考太极创客网站中关于本程序的讲解页面获取详细说明信息。网址:
// http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
if (client.connect(host, httpPort)){
Serial.println(" Success!"); // 连接成功后串口输出“Success”信息

client.print(httpRequest); // 向服务器发送HTTP请求
Serial.println("Sending request: ");// 通过串口输出HTTP请求信息内容以便查阅
Serial.println(httpRequest);

// 通过串口输出网络服务器响应信息, 以下段落中的示例程序为本程序重点2
// 请参考太极创客网站中关于本程序的讲解页面获取详细说明信息。网址:
// http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
Serial.println("Web Server Response:");
while (client.connected() || client.available()){
if (client.available()){
String line = client.readStringUntil('\n');
Serial.println(line);
}
}

client.stop(); // 断开与服务器的连接
Serial.print("Disconnected from "); // 并且通过串口输出断开连接信息
Serial.print(host);

} else{ // 如果连接不成功则通过串口输出“连接失败”信息
Serial.println(" connection failed!");
client.stop();
}
}

程序重点讲解

重点1:实现网络服务器连接

这部分逻辑判断语句中的判断条件是client.connect(host, httpPort)的返回值。ESP8266所实现的网络客户端是通过connect函数来实现与网络服务器的连接的。被连接的网络服务器网址为connect函数的第一个参数,即host。这里的第二个参数httpPort则是连接网络服务器的端口编号。关于host 和 httpPort的具体定义都在程序刚一开始的部分。

如果ESP8266所建立的网络客户端成功与网络服务器建立了连接,connect函数将会返回“真”,否则将会返回“假”。利用connect函数返回值,程序可以根据网络服务器的连接状况来决定具体执行哪一个操作。即:

– 连接成功则通过后续的while循环语句来获取网络服务器的HTTP响应信息,并且将信息通过串口输出。

– 连接不成功则通过串口输出“连接失败”信息。

重点2:获取网络服务器响应信息并且通过串口输出

这里的 while (client.connected() || client.available())循环语句判断条件由两个函数的返回值来决定。

第一个条件是 client.connected() 的返回值。connected()这个函数用于检查当前ESP8266与网络服务器的连接情况。如果连接状态为“真”,则返回真。否则返回“假”。

第二个条件是 client.available()的返回值。available()函数用于检查网络客户端是否有接收到服务器发来的信息。如果有信息则返回真,否则返回“假”。

利用以上两个条件进行“或”运算所得到的结果即是这里while循环语句的判断条件。换句话说,就是当ESP8266与服务器保持连接以及服务器有信息发送给ESP8266这两个条件满足一个,while循环语句体就会执行循环。当这两个条件都不满足了,则跳出循环。

接下来我们看一下while循环的具体内容。这里我们使用了一个逻辑判断语句。判断条件再次出现了client.available()。在ESP8266与网络服务器通过connect函数建立连接并且ESP8266发送了HTTP请求以后,ESP8266并不会马上就收到服务器的响应信息。造成这个情况的原因有很多个,其中主要原意是服务器接到HTTP响应后,也许需要处理其它客户端的响应或者进行其它工作。这就导致服务器在响应ESP8266时会产生延迟。另外我们的网络环境也会产生延迟。也就是说服务器从发出响应到我们的ESP8266接收到响应这个过程是受到到网络环境等等因素影响的。

基于以上原因,我们需要让ESP8266客户端在与网络服务器取得连接以后在原地待命。一旦ESP8266客户端接收到服务器的响应信息,available函数将会返回“真”值,这时才让ESP8266客户端开始检查收到的响应信息具体是什么。这个检查工作是通过逻辑判断语句中的,client.readStringUntil(‘\n’)来实现的。

各位需要了解一点readStringUntil函数的具体用法,就是client.readStringUntil(‘\n’)函数会将服务器响应信息中逐行分解为字符串。这些字符串会赋值给调用该函数的位置,也就是赋值给line这个字符串变量中。

实测如下,可以看到网页的响应信息就是www.example.com网站的首页HTML源代码。