从零开始的ESP8266探索(06)-使用Server功能搭建Web Server

文章目录

  • 目的
  • 开启服务器
  • 监听客户端
  • Web的请求与响应
  • 实现Web Server功能
  • 通过网页收发数据
    • 建立网页
    • 完善Web Server功能
  • 总结

目的

ESP8266可以方便的进行UDP通讯实现通过网络控制设备的功能,但是该方法对于用户来说还需要一个界面来完成数据通讯,所幸ESP系列有着不错的性能和不小的存储空间,足够用来构建简单的网页服务器(Web Server),这样用户就可以通过浏览器访问进行查看数据或控制设备。

这篇文章中更多的会涉及一些底层原理相关的内容,想要简单的使用可以参考《从零开始的ESP8266探索(09)-更加方便的ESP8266WebServer使用介绍》
如果你只是想要用TCP Server功能那也可以参考下面内容。

开启服务器

在Arduino for esp8266中启用服务功能非常简单,如下两步即可实现:

WiFiServer server(80); //建立服务器对象,设置监听端口号为80(网页默认端口号)
server.begin(); //启用服务器

只要上述两步就完成了Server的设置,接下来就是具体的处理工作了。

监听客户端

Server的具体处理事务在loop()函数中进行,首先请看下述代码:

String readString = ""; //建立一个字符串对象用来接收存放来自客户的数据

void loop()
{
    WiFiClient client = server.available(); //尝试建立客户对象
    if (client) //如果当前有客户可用
    {
        boolean currentLineIsBlank = true;
        Serial.println("[Client connected]");
        
        while (client.connected()) //如果客户端建立连接
        {
            if (client.available()) //等待有可读数据
            {
                char c = client.read(); //读取一字节数据
                readString += c; //拼接数据
                /************************************************/
                if (c == '\n' && currentLineIsBlank) //等待请求头接收完成(接收到空行)
                {
                    break;
                }

                if (c == '\n')
                {
                    currentLineIsBlank = true; //开始新行
                }
                else if (c != '\r')
                {
                    currentLineIsBlank = false; //正在接收某行中
                }
                /************************************************/
            }
        }
        delay(1); //等待客户完成接收
        client.stop(); //结束当前连接:
        Serial.println("[Client disconnected]");
        
        Serial.println(readString); //打印输出来自客户的数据
        readString = "";
    }
}

以上代码中除去/***//***/之间部分代码为监听客户端连接并接收数据功能;/***//***/之间部分代码用于对客户端的请求进行处理。将代码烧录到模块中进行测试,可以看到效果如下:

可以看到在浏览器访问Server的时候Server会接收到下面的信息:

GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, /
Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,ja;q=0.6,en-US;q=0.4,en;q=0.2
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 172.16.2.231
Connection: Keep-Alive

(还有一种GET /favicon.ico HTTP/1.1开头的,是请求图标的)
这个信息就是浏览器向Server发出的信息,到目前为止这只是一个标准的TCP Server,如果我们在收到浏览器发送的信息后做出对应的应答(HTTP协议),那这就变成了Web Server。

Web的请求与响应

上面的测试中浏览器发出的消息是什么,应该怎么处理,了解的这些就能完成完整的Web Server功能了,该部分内容可以参考如下:
从零开始的ESP8266探索(06)-使用Server功能搭建Web Server_第1张图片
从零开始的ESP8266探索(06)-使用Server功能搭建Web Server_第2张图片

实现Web Server功能

根据上文内容综合可知,对于Web Server来说只要接收到完整的请求头时返回相应的东西即可,更改上面部分代码我们的Web Server基本功能就实现了:
首先准备好响应头网页

//响应头
String responseHeaders =
    String("") +
    "HTTP/1.1 200 OK\r\n" +
    "Content-Type: text/html\r\n" +
    "Connection: close\r\n" +
    "\r\n";
//网页
String myhtmlPage = 
    String("") +
    "Hello World";

然后上文中代码改写如下:

if (c == '\n' && currentLineIsBlank) //等待请求头接收完成(接收到空行)
{
    //比较接收到的请求数据
    if (readString.startsWith("GET / HTTP/1.1")) //如果是网页请求
    {
        client.print(responseHeaders); //向客户端输出网页响应
        client.print(myhtmlPage); //向客户端输出网页内容
        client.print("\r\n");
    }
    else
    {
        client.print("\r\n");
    }
    break;
}

上述代码烧录运行后可以看到下面请,在浏览器访问时可以看到我们准备的网页内容:
从零开始的ESP8266探索(06)-使用Server功能搭建Web Server_第3张图片

通过网页收发数据

上面内容其实已经完成了基本的Web Server功能,现在我们再进一步,实现网页和服务器的数据交互功能,在这里需要用到AJAX知识,很简单,可以参考下面的教程:
http://www.w3school.com.cn/ajax/
http://www.runoob.com/ajax/ajax-tutorial.html
在下文中我们将要实现通过浏览器访问建立于ESP8266上的网页,网页中显示ESP8266模块上LED状态和一个按钮,通过点击按钮可以点亮/熄灭LED。

建立网页

首先我们准备一个网页:

<html>
<head>
    <title>ESP8266 Web Server Testtitle>
    <script defer="defer">
        function ledSwitch() {
            var xmlhttp;
            if (window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            } else {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                        document.getElementById("txtState").innerHTML = xmlhttp.responseText;
                    }
                },
            xmlhttp.open("GET", "Switch", true);
            xmlhttp.send(); 
        }
    script>
head>
<body>
    <div id="txtState">Unkwondiv>
    <input type="button" value="Switch" onclick="ledSwitch()">
body>
html>

网页初始效果如下:
从零开始的ESP8266探索(06)-使用Server功能搭建Web Server_第4张图片
网页可以通过以下网站转成字符串:
http://www.css88.com/tool/html2js/

完善Web Server功能

下面是完整的需要烧录到ESP8266中的代码:

#include 

/*** 该工程可以在2.4.0版本esp8266库中运行,没在更高版本库中进行测试 ***/

const char *ssid = "********";
const char *password = "********";

WiFiServer server(80);

String readString = ""; //建立一个字符串对象用来接收存放来自客户的数据

//响应头
String responseHeaders =
    String("") +
    "HTTP/1.1 200 OK\r\n" +
    "Content-Type: text/html\r\n" +
    "Connection: close\r\n" +
    "\r\n";

//网页
String myhtmlPage =
    String("") +
    "" +
    "" +
    "    ESP8266 Web Server Test" +
    "    " +
    "" +
    "" +
    "    
Unkwon
"
+ " " + "" + ""; bool isLedTurnOpen = false; // 记录LED状态 void setup() { pinMode(2, OUTPUT); digitalWrite(2, HIGH); // 熄灭LED Serial.begin(115200); Serial.println(); Serial.printf("Connecting to %s ", ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(" connected"); server.begin(); Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str()); } void loop() { WiFiClient client = server.available(); //尝试建立客户对象 if (client) //如果当前有客户可用 { boolean currentLineIsBlank = true; Serial.println("[Client connected]"); while (client.connected()) //如果客户端建立连接 { if (client.available()) //等待有可读数据 { char c = client.read(); //读取一字节数据 readString += c; //拼接数据 /************************************************/ if (c == '\n' && currentLineIsBlank) //等待请求头接收完成(接收到空行) { //比较接收到的请求数据 if (readString.startsWith("GET / HTTP/1.1")) //如果是网页请求 { client.print(responseHeaders); //向客户端输出网页响应 client.print(myhtmlPage); //向客户端输出网页内容 client.print("\r\n"); } else if (readString.startsWith("GET /Switch")) //如果是改变LED状态请求 { if (isLedTurnOpen == false) { digitalWrite(2, LOW); // 点亮LED client.print("LED has been turn on"); isLedTurnOpen = true; } else { digitalWrite(2, HIGH); // 熄灭LED client.print("LED has been turn off"); isLedTurnOpen = false; } } else { client.print("\r\n"); } break; } if (c == '\n') { currentLineIsBlank = true; //开始新行 } else if (c != '\r') { currentLineIsBlank = false; //正在接收某行中 } /************************************************/ } } delay(1); //等待客户完成接收 client.stop(); //结束当前连接: Serial.println("[Client disconnected]"); Serial.println(readString); //打印输出来自客户的数据 readString = ""; } }

将上面代码烧录运行可以看到下面效果:

总结

使用Arduino for esp8266可以非常简单实现Web Server功能,更多详细内容可以参考如下:
Server功能示例:
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/server-examples.html
Server功能库说明:
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/server-class.html

这篇文章中更多的会涉及一些底层原理相关的内容,想要简单的使用可以参考《从零开始的ESP8266探索(09)-更加方便的ESP8266WebServer使用介绍》

你可能感兴趣的:(ESP8266相关)