参考教程https://www.bilibili.com/video/BV1L7411c7jw/?spm_id_from333.1387.favlist.content.click七、ESP8266作为网络客户端1、ESP8266作为网络客户端的行为1网络客户端有很多种类型像日常生活中使用的手机、电脑以及ESP866-NodeMCU开发板都可以作为网络客户端向服务器发出请求。2如果ESP866-NodeMCU作为客户端接入一个与互联网连接的Wi-Fi网络中那么ESP866-NodeMCU想要访问其它服务器的网站首页大致流程如下所示。2、使用ESP8266HTTPClient库实现网络通讯1HTTPClient类是使用HTTP协议的网络客户端的抽象该类的成员函数有如下几个包括但不限于①begin函数初始化HTTP请求并设置目标地址URL请求路径并返回设置结果True表示准备就绪False表示URL格式错误或内存不足。该函数有多种重载形式最常用的是只有一个参数的重载形式参数为指定URL的字符串类型数据②GET函数使用GET方法发送HTTP请求并返回服务器响应的状态码该函数无参数。③POST函数使用POST方法发送HTTP请求并返回服务器响应的状态码该函数无参数。④getString函数获取服务器HTTP响应报文中响应体的内容以字符串的形式返回该函数无参数。⑤end函数关闭ESP8266与服务器的连接该函数无参数。2使用ESP8266连接外部服务器请求网址“http://www.example.com”的信息其程序流程如下图所示。3将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可请求网址“http://www.example.com”的信息并将返回的内容打印在串口监视器中。#include ESP8266WiFi.h #include ESP8266HTTPClient.h #define URL http://www.example.com //测试HTTP请求用的URL注意网址前面必须添加http:// void setup() { Serial.begin(9600); WiFi.mode(WIFI_STA); //设置ESP8266工作模式为无线终端模式 WiFi.begin(Zevalin_Computer, 00114514); //连接Wi-Fi //等待Wi-Fi连接 while(WiFi.status() ! WL_CONNECTED){ delay(1000); Serial.print(.); } Serial.println(); Serial.print(WiFi Connected!); httpClientRequest(); //发送HTTP请求 } void loop(){ } //发送HTTP请求并且将服务器响应通过串口输出 void httpClientRequest(){ //创建 HTTPClient 对象 HTTPClient httpClient; //通过begin函数配置请求地址 httpClient.begin(URL); Serial.print(URL: ); Serial.println(URL); //通过GET函数启动连接并发送HTTP请求 int httpCode httpClient.GET(); Serial.print(Send GET request to URL: ); Serial.println(URL); //如果服务器响应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); } //关闭ESP8266与服务器连接 httpClient.end(); }①WiFi.mode(val)配置ESP8266以val参数指定的模式工作val的可选项有WIFI_OFF关闭Wi-Fi、WIFI_STA无线终端模式、WIFI_AP接入点模式、WIFI_AP_STA接入点-无线终端双模式。②WiFi.begin(ssid, password)控制ESP8266接入Wi-Fi网络其中ssid参数为Wi-Fi网络名password为Wi-Fi网络密码。3、使用WiFiClient库实现网络通讯1WiFiClient类是使用Wi-Fi接入互联网的网络客户端的抽象它比HTTPClient类的局限性更小也就是不局限于使用HTTP协议该类的成员函数有如下几个包括但不限于①print函数向服务器发送HTTP请求报文函数参数为字符串类型的报文内容报文内容需要程序员按照通信协议的格式自行构建下图所示的是HTTP请求报文格式CLRF为换行符。②connect函数与服务器建立连接第一个参数为被连接网络服务器的网址第二个参数为被连接网络服务器的端口编号HTTP协议的熟知端口号为80。③connected函数如果ESP8266已与服务器建立连接则返回True否则返回False该函数无参数。④available函数如果ESP8266接收到服务器返回的响应信息则返回True否则返回False该函数无参数。⑤readStringUntil函数获取服务器返回的响应信息直到遇到指定字符返回字符串类型数据该指定字符即为函数参数。⑥find函数获取服务器返回的响应信息判断响应信息中有没有指定字符串该指定字符串即为函数参数有指定字符串则返回True否则返回False。2使用ESP8266连接外部服务器请求网址“http://www.example.com”的信息其程序流程如下图所示。3将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可请求网址“http://www.example.com”的信息并将返回的内容打印在串口监视器中。#include ESP8266WiFi.h const char* host www.example.com; // 目标网络服务器地址 const int httpPort 80; // http熟知端口号 void setup(){ Serial.begin(9600); Serial.println(); WiFi.mode(WIFI_STA); //设置ESP8266工作模式为无线终端模式 WiFi.begin(Zevalin_Computer, 00114514); //连接Wi-Fi //等待Wi-Fi连接 while(WiFi.status() ! WL_CONNECTED){ delay(1000); Serial.print(.); } Serial.println(); Serial.println(WiFi Connected!); wifiClientRequest(); } void loop(){ } // 向服务器发送HTTP请求 void wifiClientRequest(){ // 建立Wi-Fi客户端对象对象名称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); // 连接网络服务器 if(client.connect(host, httpPort)){ Serial.println( Success!); // 连接成功后串口输出“Success”信息 client.print(httpRequest); // 向服务器发送HTTP请求 Serial.println(Sending request: );// 通过串口输出HTTP请求信息内容 Serial.println(httpRequest); // 通过串口输出网络服务器响应信息 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(); } }4、使用WiFiServer库建立ESP8266网络服务器1WiFiServer类是使用Wi-Fi网络接入互联网的服务器的抽象创建对象时需将应用层服务对应的运输层端口号传入构造函数中针对HTTP协议其使用的运输层熟知端口号为80。之所以在本节介绍它是因为它要配合WiFiClient类使用服务器为了管理客户端会将其抽象为WiFiClient对象进而进行其它操作。而本节中使用到WiFiServer库提供的函数如下①available函数WiFiServer类的成员等待并接受一个新的客户端连接请求当有客户端试图连接到ESP8266创建的服务器时这个函数会把它“接进来”并返回一个WiFiClient对象之后就可以通过这个对象和该客户端互相发送数据了如果没有客户端试图连接服务器将返回空值该函数无参数。②print函数WiFiClient类成员对WiFiClient对象抽象的客户端发送服务器响应消息函数参数为响应报文字符串。③stop函数WiFiClient类成员结束WiFiClient对象抽象的客户端与服务器的连接该函数无参数。2将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板开启电脑热点“Zevalin_Computer”ESP8266会建立起一个小型服务器接下来打开浏览器在地址栏中输入NodeMCU的IP地址并按下回车可以看到“client_request_received”的文本信息。#include ESP8266WiFi.h const char* ssid Zevalin_Computer; const char* password 00114514; WiFiServer server(80); void setup(){ Serial.begin(9600); Serial.println(); WiFi.begin(ssid, password); while(WiFi.status() ! WL_CONNECTED){ delay(500); Serial.print(F(.)); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); server.begin(); } void loop(){ runServer(); // 运行服务器 } void runServer(){ // 建立WiFiClient对象用于处理客户端请求信息 WiFiClient incomingClient server.available(); // 如果没有客户端请求信息则“跳过”函数中后续程序内容 if (!incomingClient) { return; } Serial.println(Client Connected); String clientRequest incomingClient.readString(); Serial.print(clientRequest); // 建立服务器响应信息 String httpResponse HTTP/1.0 200 OK\r\n Connection: close\r\n Content-Type: text/plain;\r\n \r\n client_request_received; // 向客户端发送以上服务器响应信息 incomingClient.print(httpResponse); incomingClient.stop(); Serial.println(incomingClient stop); }5、Stream在ESP8266中的应用1Stream对于ESP8266-Arduino语言来说指的是数据序列。在C编程中Stream常被翻译作“流”只是将Stream称为“数据序列”语意更加直观明确因为数据序列这一概念有两个很关键特点第一个特点是“序”即数据序列不能是杂乱无章的数据罗列第二个特点是“列”即数据序列是排成一列的。2Stream是ESP8266-Arduino开发环境中的一种数据类型Serial库、WiFiClient库、FS库所建立的对象都可以处理Stream数据。另外除了以上这些库以外以下列表中的库也可以处理Stream数据当然这并不意味着这些库所拥有的函数都是一样的。库类SerialSerialSoftwareSerialSoftwareSerialEhternetEthernetClientESP8266FSFileSDFileWireWireGSMGSMClientWifiClientWiFiClientWiFiServerWiFiServerWiFiUDPWiFiUDPWiFiClientSecureWiFiClientSecure八、ESP8266 HTTP协议数据通讯1、客户端向服务器发送数据信息1在这个示例中两块ESP8266连接同一个Wi-Fi网络一块作为服务器另一块作为客户端ESP8266客户端将会通过HTTP协议向ESP8266服务器发送信息最终实现的效果是通过客户端ESP8266开发板上的按键来“遥控”服务器上的LED点亮和熄灭。①在运行过程中客户端ESP8266将会实时检测板上的按键状态并且把按键状态发送给服务器。②服务器在接收到客户端按键状态后可以根据客户端按键状态来控制服务器端板上的LED点亮和熄灭。2服务器端程序①程序任务[1]接收客户端发来的HTTP请求并且解析信息中的数据信息。[2]将解析的数据信息通过串口监视器显示供用户查看。[3]将解析的客户端按键状态信息用于控制服务器端板上LED的点亮和熄灭。②程序框图③程序代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h // 使用WiFiMulti库 #include ESP8266WebServer.h // 使用WebServer库 ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是 wifiMulti ESP8266WebServer server(80); // 建立网络服务器对象该对象用于响应HTTP请求 IPAddress local_IP(192, 168, 10, 135); // ESP8266-NodeMCU联网后的IP IPAddress gateway(192, 168, 10, 1); // 网关IP通常网关IP是WiFI路由IP IPAddress subnet(255, 255, 255, 0); // 子网掩码 IPAddress dns(192, 168, 10, 1); // 局域网DNS的IP通常局域网DNS的IP是Wi-FI路由的IP void setup(void){ Serial.begin(9600); // 启动串口通讯 Serial.println(); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // 设置开发板网络环境配置开发板、网关的IP地址及子网掩码局域网DNS的IP可选非必须配置 if(!WiFi.config(local_IP, gateway, subnet)) { Serial.println(Failed to Config ESP8266 IP); } wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); while (wifiMulti.run() ! WL_CONNECTED) { delay(250); Serial.print(.); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); server.on(/update, handleUpdate); // 配置处理/update请求的函数 server.begin(); // 启动网站服务 Serial.println(HTTP server started); } void loop(void){ server.handleClient(); // 检查http服务器访问 } void handleUpdate(){ float floatValue server.arg(float).toFloat(); // 获取客户端发送HTTP信息中的浮点数值 int intValue server.arg(int).toInt(); // 获取客户端发送HTTP信息中的整数数值 int buttonValue server.arg(button).toInt(); // 获取客户端发送HTTP信息中的按键控制量 server.send(200, text/plain, Received); // 发送http响应 buttonValue 0 ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); // 通过串口监视器输出获取到的变量数值 Serial.print(floatValue ); Serial.println(floatValue); Serial.print(intValue ); Serial.println(intValue); Serial.print(buttonValue ); Serial.println(buttonValue); Serial.println(); }[1]IPAddress是类对IP地址的抽象创建IPAddress类时构造函数的参数为IP地址各组的数值其中每8位为一组IPv4。[2]WiFi.config函数用于配置开发板、网关的IP地址及子网掩码局域网DNS的IP地址是可选参数非必须配置。3客户端程序①程序任务[1]客户端通过HTTP协议向服务器发送信息。[2]信息中包含客户端按键开关引脚状态用于控制服务器板上LED的点亮和熄灭。[3]信息中包含测试数据。②程序框图③程序代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h // 使用WiFiMulti库 #define buttonPin D3 // 按钮引脚D3 ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象对象名称是 wifiMulti bool buttonState; // 存储客户端按键控制数据 float clientFloatValue; // 存储客户端发送的浮点型测试数据 int clientIntValue; // 存储客户端发送的整数型测试数据 const char* host 192.168.10.135; // 即将连接服务器的网址/IP地址 const int httpPort 80; // 即将连接服务器的端口 void setup(void){ Serial.begin(9600); Serial.println(); pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式 wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); while(wifiMulti.run() ! WL_CONNECTED){ delay(250); Serial.print(.); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); } void loop(void){ // 获取按键引脚状态 buttonState digitalRead(buttonPin); // 改变测试用变量数值用于服务器端接收数据检测 clientFloatValue 1.5; clientIntValue 2; // 向服务器发送请求 wifiClientRequest(); delay(1000); } void wifiClientRequest(){ WiFiClient client; // 将需要发送的数据信息放入客户端请求 String url /update?float String(clientFloatValue) int String(clientIntValue) button String(buttonState); // 建立字符串用于HTTP请求 String httpRequest String(GET ) url HTTP/1.1\r\n Host: host \r\n Connection: close\r\n \r\n; Serial.print(Connecting to ); Serial.print(host); if (client.connect(host, httpPort)){ Serial.println( Sucess); client.print(httpRequest); // 向服务器发送HTTP请求 Serial.println(Sending request: ); // 通过串口输出HTTP请求信息内容 Serial.println(httpRequest); } else{ Serial.println( failed); //如果连接失败则串口输出信息告知用户 } client.stop(); }2、客户端向服务器请求数据信息1在这个示例中两块ESP8266连接同一个Wi-Fi网络一块作为服务器另一块作为客户端ESP8266客户端将会通过HTTP协议向ESP8266服务器发送信息最终实现的效果是通过控制服务器端的板上按键可以控制客户端板上LED的点亮和熄灭。①在运行过程中服务器端ESP8266将会实时检测板上的按键状态。②客户端每隔一段时间向服务器请求按键状态在接收到服务器端发回的按键状态后可以根据按键状态来控制服务器端板上的LED点亮和熄灭。2服务器端程序①程序任务[1]实时获取服务器端开发板上按钮引脚状态。[2]当有客户端向ESP8266服务器的“/update”路径发送请求时将服务器的按键引脚状态通过响应信息回复给客户端。②程序框图③程序代码#include ESP8266WiFi.h // ESP8266WiFi库 #include ESP8266WiFiMulti.h // ESP8266WiFiMulti库 #include ESP8266WebServer.h // ESP8266WebServer库 #define buttonPin D3 // 按钮引脚D3 ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是wifiMulti ESP8266WebServer esp8266_server(80); // 建立网络服务器对象该对象用于响应HTTP请求 IPAddress local_IP(192, 168, 10, 135); // ESP8266-NodeMCU联网后的IP IPAddress gateway(192, 168, 10, 1); // 网关IP通常网关IP是WiFI路由IP IPAddress subnet(255, 255, 255, 0); // 子网掩码 IPAddress dns(192, 168, 10, 1); // 局域网DNS的IP通常局域网DNS的IP是Wi-FI路由的IP bool pinState; // 存储引脚状态用变量 void setup(){ Serial.begin(9600); Serial.println(); pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式 if(!WiFi.config(local_IP, gateway, subnet)){ Serial.println(Failed to ESP8266 IP); } wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); int i 0; while(wifiMulti.run() ! WL_CONNECTED){ delay(1000); Serial.print(i); Serial.print( ); } Serial.println(); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); esp8266_server.on(/update, handleUpdate); // 配置处理/update请求的函数 esp8266_server.begin(); // 启动网站服务 Serial.println(HTTP esp8266_server started); } void loop(){ pinState digitalRead(buttonPin); // 获取引脚状态 esp8266_server.handleClient(); // 处理客户端的请求 } void handleUpdate(){ String pinStateStr; pinState HIGH ? pinStateStr 1 : pinStateStr 0; //根据D3引脚电平构建HTTP响应信息 esp8266_server.send(200, text/html, buttonState: pinStateStr); }3客户端程序①程序任务[1]定时向服务器发送请求从而获取服务器开发板上按钮状态。[2]将服务器端发来的按钮引脚电平状态解析为数字量并且用该数字量控制板上LED点亮和熄灭。②程序框图③程序代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象 const char* host 192.168.10.135; // 网络服务器IP const int httpPort 80; // http熟知端口80 void setup(){ Serial.begin(9600); Serial.println(); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); int i 0; while(wifiMulti.run() ! WL_CONNECTED){ delay(1000); Serial.print(i); Serial.print( ); } Serial.println(); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); } void loop(){ wifiClientRequest(); delay(3000); } void wifiClientRequest(){ WiFiClient client; // 建立WiFiClient对象 bool buttonState; // 储存服务器按钮状态变量 Serial.print(Connecting to ); Serial.print(host); // 连接服务器 if (client.connect(host, httpPort)){ Serial.println( Success!); // 建立客户端请求信息 String httpRequest String(GET /update) HTTP/1.1\r\n Host: host \r\n Connection: close\r\n \r\n; // 发送客户端请求 Serial.println(Sending request: );Serial.print(httpRequest); client.print(httpRequest); // 获取服务器响应信息中的按钮状态信息 while(client.connected() || client.available()){ if(client.find(buttonState:)){ buttonState client.parseInt(); Serial.print(buttonState: ); Serial.println(buttonState); } } } else{ Serial.println( failed!); } Serial.println(); client.stop(); // 根据服务器按键状态点亮或熄灭LED buttonState 0 ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); }
零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(四)
参考教程https://www.bilibili.com/video/BV1L7411c7jw/?spm_id_from333.1387.favlist.content.click七、ESP8266作为网络客户端1、ESP8266作为网络客户端的行为1网络客户端有很多种类型像日常生活中使用的手机、电脑以及ESP866-NodeMCU开发板都可以作为网络客户端向服务器发出请求。2如果ESP866-NodeMCU作为客户端接入一个与互联网连接的Wi-Fi网络中那么ESP866-NodeMCU想要访问其它服务器的网站首页大致流程如下所示。2、使用ESP8266HTTPClient库实现网络通讯1HTTPClient类是使用HTTP协议的网络客户端的抽象该类的成员函数有如下几个包括但不限于①begin函数初始化HTTP请求并设置目标地址URL请求路径并返回设置结果True表示准备就绪False表示URL格式错误或内存不足。该函数有多种重载形式最常用的是只有一个参数的重载形式参数为指定URL的字符串类型数据②GET函数使用GET方法发送HTTP请求并返回服务器响应的状态码该函数无参数。③POST函数使用POST方法发送HTTP请求并返回服务器响应的状态码该函数无参数。④getString函数获取服务器HTTP响应报文中响应体的内容以字符串的形式返回该函数无参数。⑤end函数关闭ESP8266与服务器的连接该函数无参数。2使用ESP8266连接外部服务器请求网址“http://www.example.com”的信息其程序流程如下图所示。3将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可请求网址“http://www.example.com”的信息并将返回的内容打印在串口监视器中。#include ESP8266WiFi.h #include ESP8266HTTPClient.h #define URL http://www.example.com //测试HTTP请求用的URL注意网址前面必须添加http:// void setup() { Serial.begin(9600); WiFi.mode(WIFI_STA); //设置ESP8266工作模式为无线终端模式 WiFi.begin(Zevalin_Computer, 00114514); //连接Wi-Fi //等待Wi-Fi连接 while(WiFi.status() ! WL_CONNECTED){ delay(1000); Serial.print(.); } Serial.println(); Serial.print(WiFi Connected!); httpClientRequest(); //发送HTTP请求 } void loop(){ } //发送HTTP请求并且将服务器响应通过串口输出 void httpClientRequest(){ //创建 HTTPClient 对象 HTTPClient httpClient; //通过begin函数配置请求地址 httpClient.begin(URL); Serial.print(URL: ); Serial.println(URL); //通过GET函数启动连接并发送HTTP请求 int httpCode httpClient.GET(); Serial.print(Send GET request to URL: ); Serial.println(URL); //如果服务器响应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); } //关闭ESP8266与服务器连接 httpClient.end(); }①WiFi.mode(val)配置ESP8266以val参数指定的模式工作val的可选项有WIFI_OFF关闭Wi-Fi、WIFI_STA无线终端模式、WIFI_AP接入点模式、WIFI_AP_STA接入点-无线终端双模式。②WiFi.begin(ssid, password)控制ESP8266接入Wi-Fi网络其中ssid参数为Wi-Fi网络名password为Wi-Fi网络密码。3、使用WiFiClient库实现网络通讯1WiFiClient类是使用Wi-Fi接入互联网的网络客户端的抽象它比HTTPClient类的局限性更小也就是不局限于使用HTTP协议该类的成员函数有如下几个包括但不限于①print函数向服务器发送HTTP请求报文函数参数为字符串类型的报文内容报文内容需要程序员按照通信协议的格式自行构建下图所示的是HTTP请求报文格式CLRF为换行符。②connect函数与服务器建立连接第一个参数为被连接网络服务器的网址第二个参数为被连接网络服务器的端口编号HTTP协议的熟知端口号为80。③connected函数如果ESP8266已与服务器建立连接则返回True否则返回False该函数无参数。④available函数如果ESP8266接收到服务器返回的响应信息则返回True否则返回False该函数无参数。⑤readStringUntil函数获取服务器返回的响应信息直到遇到指定字符返回字符串类型数据该指定字符即为函数参数。⑥find函数获取服务器返回的响应信息判断响应信息中有没有指定字符串该指定字符串即为函数参数有指定字符串则返回True否则返回False。2使用ESP8266连接外部服务器请求网址“http://www.example.com”的信息其程序流程如下图所示。3将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可请求网址“http://www.example.com”的信息并将返回的内容打印在串口监视器中。#include ESP8266WiFi.h const char* host www.example.com; // 目标网络服务器地址 const int httpPort 80; // http熟知端口号 void setup(){ Serial.begin(9600); Serial.println(); WiFi.mode(WIFI_STA); //设置ESP8266工作模式为无线终端模式 WiFi.begin(Zevalin_Computer, 00114514); //连接Wi-Fi //等待Wi-Fi连接 while(WiFi.status() ! WL_CONNECTED){ delay(1000); Serial.print(.); } Serial.println(); Serial.println(WiFi Connected!); wifiClientRequest(); } void loop(){ } // 向服务器发送HTTP请求 void wifiClientRequest(){ // 建立Wi-Fi客户端对象对象名称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); // 连接网络服务器 if(client.connect(host, httpPort)){ Serial.println( Success!); // 连接成功后串口输出“Success”信息 client.print(httpRequest); // 向服务器发送HTTP请求 Serial.println(Sending request: );// 通过串口输出HTTP请求信息内容 Serial.println(httpRequest); // 通过串口输出网络服务器响应信息 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(); } }4、使用WiFiServer库建立ESP8266网络服务器1WiFiServer类是使用Wi-Fi网络接入互联网的服务器的抽象创建对象时需将应用层服务对应的运输层端口号传入构造函数中针对HTTP协议其使用的运输层熟知端口号为80。之所以在本节介绍它是因为它要配合WiFiClient类使用服务器为了管理客户端会将其抽象为WiFiClient对象进而进行其它操作。而本节中使用到WiFiServer库提供的函数如下①available函数WiFiServer类的成员等待并接受一个新的客户端连接请求当有客户端试图连接到ESP8266创建的服务器时这个函数会把它“接进来”并返回一个WiFiClient对象之后就可以通过这个对象和该客户端互相发送数据了如果没有客户端试图连接服务器将返回空值该函数无参数。②print函数WiFiClient类成员对WiFiClient对象抽象的客户端发送服务器响应消息函数参数为响应报文字符串。③stop函数WiFiClient类成员结束WiFiClient对象抽象的客户端与服务器的连接该函数无参数。2将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板开启电脑热点“Zevalin_Computer”ESP8266会建立起一个小型服务器接下来打开浏览器在地址栏中输入NodeMCU的IP地址并按下回车可以看到“client_request_received”的文本信息。#include ESP8266WiFi.h const char* ssid Zevalin_Computer; const char* password 00114514; WiFiServer server(80); void setup(){ Serial.begin(9600); Serial.println(); WiFi.begin(ssid, password); while(WiFi.status() ! WL_CONNECTED){ delay(500); Serial.print(F(.)); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); server.begin(); } void loop(){ runServer(); // 运行服务器 } void runServer(){ // 建立WiFiClient对象用于处理客户端请求信息 WiFiClient incomingClient server.available(); // 如果没有客户端请求信息则“跳过”函数中后续程序内容 if (!incomingClient) { return; } Serial.println(Client Connected); String clientRequest incomingClient.readString(); Serial.print(clientRequest); // 建立服务器响应信息 String httpResponse HTTP/1.0 200 OK\r\n Connection: close\r\n Content-Type: text/plain;\r\n \r\n client_request_received; // 向客户端发送以上服务器响应信息 incomingClient.print(httpResponse); incomingClient.stop(); Serial.println(incomingClient stop); }5、Stream在ESP8266中的应用1Stream对于ESP8266-Arduino语言来说指的是数据序列。在C编程中Stream常被翻译作“流”只是将Stream称为“数据序列”语意更加直观明确因为数据序列这一概念有两个很关键特点第一个特点是“序”即数据序列不能是杂乱无章的数据罗列第二个特点是“列”即数据序列是排成一列的。2Stream是ESP8266-Arduino开发环境中的一种数据类型Serial库、WiFiClient库、FS库所建立的对象都可以处理Stream数据。另外除了以上这些库以外以下列表中的库也可以处理Stream数据当然这并不意味着这些库所拥有的函数都是一样的。库类SerialSerialSoftwareSerialSoftwareSerialEhternetEthernetClientESP8266FSFileSDFileWireWireGSMGSMClientWifiClientWiFiClientWiFiServerWiFiServerWiFiUDPWiFiUDPWiFiClientSecureWiFiClientSecure八、ESP8266 HTTP协议数据通讯1、客户端向服务器发送数据信息1在这个示例中两块ESP8266连接同一个Wi-Fi网络一块作为服务器另一块作为客户端ESP8266客户端将会通过HTTP协议向ESP8266服务器发送信息最终实现的效果是通过客户端ESP8266开发板上的按键来“遥控”服务器上的LED点亮和熄灭。①在运行过程中客户端ESP8266将会实时检测板上的按键状态并且把按键状态发送给服务器。②服务器在接收到客户端按键状态后可以根据客户端按键状态来控制服务器端板上的LED点亮和熄灭。2服务器端程序①程序任务[1]接收客户端发来的HTTP请求并且解析信息中的数据信息。[2]将解析的数据信息通过串口监视器显示供用户查看。[3]将解析的客户端按键状态信息用于控制服务器端板上LED的点亮和熄灭。②程序框图③程序代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h // 使用WiFiMulti库 #include ESP8266WebServer.h // 使用WebServer库 ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是 wifiMulti ESP8266WebServer server(80); // 建立网络服务器对象该对象用于响应HTTP请求 IPAddress local_IP(192, 168, 10, 135); // ESP8266-NodeMCU联网后的IP IPAddress gateway(192, 168, 10, 1); // 网关IP通常网关IP是WiFI路由IP IPAddress subnet(255, 255, 255, 0); // 子网掩码 IPAddress dns(192, 168, 10, 1); // 局域网DNS的IP通常局域网DNS的IP是Wi-FI路由的IP void setup(void){ Serial.begin(9600); // 启动串口通讯 Serial.println(); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // 设置开发板网络环境配置开发板、网关的IP地址及子网掩码局域网DNS的IP可选非必须配置 if(!WiFi.config(local_IP, gateway, subnet)) { Serial.println(Failed to Config ESP8266 IP); } wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); while (wifiMulti.run() ! WL_CONNECTED) { delay(250); Serial.print(.); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); server.on(/update, handleUpdate); // 配置处理/update请求的函数 server.begin(); // 启动网站服务 Serial.println(HTTP server started); } void loop(void){ server.handleClient(); // 检查http服务器访问 } void handleUpdate(){ float floatValue server.arg(float).toFloat(); // 获取客户端发送HTTP信息中的浮点数值 int intValue server.arg(int).toInt(); // 获取客户端发送HTTP信息中的整数数值 int buttonValue server.arg(button).toInt(); // 获取客户端发送HTTP信息中的按键控制量 server.send(200, text/plain, Received); // 发送http响应 buttonValue 0 ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); // 通过串口监视器输出获取到的变量数值 Serial.print(floatValue ); Serial.println(floatValue); Serial.print(intValue ); Serial.println(intValue); Serial.print(buttonValue ); Serial.println(buttonValue); Serial.println(); }[1]IPAddress是类对IP地址的抽象创建IPAddress类时构造函数的参数为IP地址各组的数值其中每8位为一组IPv4。[2]WiFi.config函数用于配置开发板、网关的IP地址及子网掩码局域网DNS的IP地址是可选参数非必须配置。3客户端程序①程序任务[1]客户端通过HTTP协议向服务器发送信息。[2]信息中包含客户端按键开关引脚状态用于控制服务器板上LED的点亮和熄灭。[3]信息中包含测试数据。②程序框图③程序代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h // 使用WiFiMulti库 #define buttonPin D3 // 按钮引脚D3 ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象对象名称是 wifiMulti bool buttonState; // 存储客户端按键控制数据 float clientFloatValue; // 存储客户端发送的浮点型测试数据 int clientIntValue; // 存储客户端发送的整数型测试数据 const char* host 192.168.10.135; // 即将连接服务器的网址/IP地址 const int httpPort 80; // 即将连接服务器的端口 void setup(void){ Serial.begin(9600); Serial.println(); pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式 wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); while(wifiMulti.run() ! WL_CONNECTED){ delay(250); Serial.print(.); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); } void loop(void){ // 获取按键引脚状态 buttonState digitalRead(buttonPin); // 改变测试用变量数值用于服务器端接收数据检测 clientFloatValue 1.5; clientIntValue 2; // 向服务器发送请求 wifiClientRequest(); delay(1000); } void wifiClientRequest(){ WiFiClient client; // 将需要发送的数据信息放入客户端请求 String url /update?float String(clientFloatValue) int String(clientIntValue) button String(buttonState); // 建立字符串用于HTTP请求 String httpRequest String(GET ) url HTTP/1.1\r\n Host: host \r\n Connection: close\r\n \r\n; Serial.print(Connecting to ); Serial.print(host); if (client.connect(host, httpPort)){ Serial.println( Sucess); client.print(httpRequest); // 向服务器发送HTTP请求 Serial.println(Sending request: ); // 通过串口输出HTTP请求信息内容 Serial.println(httpRequest); } else{ Serial.println( failed); //如果连接失败则串口输出信息告知用户 } client.stop(); }2、客户端向服务器请求数据信息1在这个示例中两块ESP8266连接同一个Wi-Fi网络一块作为服务器另一块作为客户端ESP8266客户端将会通过HTTP协议向ESP8266服务器发送信息最终实现的效果是通过控制服务器端的板上按键可以控制客户端板上LED的点亮和熄灭。①在运行过程中服务器端ESP8266将会实时检测板上的按键状态。②客户端每隔一段时间向服务器请求按键状态在接收到服务器端发回的按键状态后可以根据按键状态来控制服务器端板上的LED点亮和熄灭。2服务器端程序①程序任务[1]实时获取服务器端开发板上按钮引脚状态。[2]当有客户端向ESP8266服务器的“/update”路径发送请求时将服务器的按键引脚状态通过响应信息回复给客户端。②程序框图③程序代码#include ESP8266WiFi.h // ESP8266WiFi库 #include ESP8266WiFiMulti.h // ESP8266WiFiMulti库 #include ESP8266WebServer.h // ESP8266WebServer库 #define buttonPin D3 // 按钮引脚D3 ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是wifiMulti ESP8266WebServer esp8266_server(80); // 建立网络服务器对象该对象用于响应HTTP请求 IPAddress local_IP(192, 168, 10, 135); // ESP8266-NodeMCU联网后的IP IPAddress gateway(192, 168, 10, 1); // 网关IP通常网关IP是WiFI路由IP IPAddress subnet(255, 255, 255, 0); // 子网掩码 IPAddress dns(192, 168, 10, 1); // 局域网DNS的IP通常局域网DNS的IP是Wi-FI路由的IP bool pinState; // 存储引脚状态用变量 void setup(){ Serial.begin(9600); Serial.println(); pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式 if(!WiFi.config(local_IP, gateway, subnet)){ Serial.println(Failed to ESP8266 IP); } wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); int i 0; while(wifiMulti.run() ! WL_CONNECTED){ delay(1000); Serial.print(i); Serial.print( ); } Serial.println(); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); esp8266_server.on(/update, handleUpdate); // 配置处理/update请求的函数 esp8266_server.begin(); // 启动网站服务 Serial.println(HTTP esp8266_server started); } void loop(){ pinState digitalRead(buttonPin); // 获取引脚状态 esp8266_server.handleClient(); // 处理客户端的请求 } void handleUpdate(){ String pinStateStr; pinState HIGH ? pinStateStr 1 : pinStateStr 0; //根据D3引脚电平构建HTTP响应信息 esp8266_server.send(200, text/html, buttonState: pinStateStr); }3客户端程序①程序任务[1]定时向服务器发送请求从而获取服务器开发板上按钮状态。[2]将服务器端发来的按钮引脚电平状态解析为数字量并且用该数字量控制板上LED点亮和熄灭。②程序框图③程序代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象 const char* host 192.168.10.135; // 网络服务器IP const int httpPort 80; // http熟知端口80 void setup(){ Serial.begin(9600); Serial.println(); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); int i 0; while(wifiMulti.run() ! WL_CONNECTED){ delay(1000); Serial.print(i); Serial.print( ); } Serial.println(); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); } void loop(){ wifiClientRequest(); delay(3000); } void wifiClientRequest(){ WiFiClient client; // 建立WiFiClient对象 bool buttonState; // 储存服务器按钮状态变量 Serial.print(Connecting to ); Serial.print(host); // 连接服务器 if (client.connect(host, httpPort)){ Serial.println( Success!); // 建立客户端请求信息 String httpRequest String(GET /update) HTTP/1.1\r\n Host: host \r\n Connection: close\r\n \r\n; // 发送客户端请求 Serial.println(Sending request: );Serial.print(httpRequest); client.print(httpRequest); // 获取服务器响应信息中的按钮状态信息 while(client.connected() || client.available()){ if(client.find(buttonState:)){ buttonState client.parseInt(); Serial.print(buttonState: ); Serial.println(buttonState); } } } else{ Serial.println( failed!); } Serial.println(); client.stop(); // 根据服务器按键状态点亮或熄灭LED buttonState 0 ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); }