ESP8266能够方便的进行UDP通信实现经过网络控制设备的功能,可是该方法对于用户来讲还须要一个界面来完成数据通信,所幸ESP系列有着不错的性能和不小的存储空间,足够用来构建简单的网页服务器(Web Server),这样用户就能够经过浏览器访问进行查看数据或控制设备。javascript
这篇文章中更多的会涉及一些底层原理相关的内容,想要简单的使用能够参考《从零开始的ESP8266探索(09)-更加方便的ESP8266WebServer使用介绍》
若是你只是想要用TCP Server功能那也能够参考下面内容。css
在Arduino for esp8266中启用服务功能很是简单,以下两步便可实现:html
WiFiServer server(80); //创建服务器对象,设置监听端口号为80(网页默认端口号) server.begin(); //启用服务器
只要上述两步就完成了Server的设置,接下来就是具体的处理工做了。java
Server的具体处理事务在loop()函数中进行,首先请看下述代码:git
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会接收到下面的信息:web
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-Aliveajax
(还有一种GET /favicon.ico HTTP/1.1开头的,是请求图标的)
这个信息就是浏览器向Server发出的信息,到目前为止这只是一个标准的TCP Server,若是咱们在收到浏览器发送的信息后作出对应的应答(HTTP协议),那这就变成了Web Server。浏览器
上面的测试中浏览器发出的消息是什么,应该怎么处理,了解的这些就能完成完整的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; }
上述代码烧录运行后能够看到下面请,在浏览器访问时能够看到咱们准备的网页内容:
上面内容其实已经完成了基本的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 Test</title> <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">Unkwon</div> <input type="button" value="Switch" onclick="ledSwitch()"> </body> </html>
网页初始效果以下:
网页能够经过如下网站转成字符串:
http://www.css88.com/tool/html2js/
下面是完整的须要烧录到ESP8266中的代码:
#include <ESP8266WiFi.h> /*** 该工程能够在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("") + "<html>" + "<head>" + " <title>ESP8266 Web Server Test</title>" + " <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\">Unkwon</div>" + " <input type=\"button\" value=\"Switch\" οnclick=\"ledSwitch()\">" + "</body>" + "</html>"; 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使用介绍》