这部分并不好写,内容很庞杂,会分成若干部分。
网络协议我们在前面已经提及,TCP/IP协议就是最重要的网络协议。在AT指令和lua固件的例程中,我们建立了TCP/IP的客户端和服务器,实现无线通信和远程控制。在电脑端,我们可以用TCP/IP的网络调试助手,也可以用c++或python自己编写客户端和服务器,和nodemcu通信。
但是今天我们就要谈谈更exciting,也是应用最广泛的网络协议:
这两本书是TCP/IP协议的经典之作,因为版权问题,恕在下不能给出链接
- computer networking, a top-down approach.
Jim Kuross & Keith Ross
不少国外大学的制定教材,通俗易懂,入门必备
- TCP/IP Illustrated, Volume 1, The Protocols.
W. Richard Stevens
被誉为网络圣经的第一卷,经典中的经典,网络工程师人手一本。不过内容组织上和上一本正相反,是从下到上
既然要讲超文本传输协议,就不能不提超文本标记语言HTML,相信大家都有了解
- Head First HTML with CSS.
Elisabeth Freeman & Eric Freeman.
本来学语言就很痛苦,还要看学霸白富美和高富帅秀恩爱,实在有点不能忍。
但是,这本书确实经典,在排行榜上一直领先。排版非常活剥,效果也不错,可以很快上手
如果想更深入,可以看下面这两本,主要针对HTML的具体样式:CSS(层叠样式表):
- Css Mastery Advanced Web Standards Solutions.
Andy Budd with Cameron Moll and Simon Collison
- CSS, the Definitive Guide.
Eric A. Meyer
即超文本传输协议,是互联网的核心。 我们上网happy刷的网页都是基于HTTP协议。
HTTP和Hypertext出现之前,网络只是用在大学和研究机构中,传个实验数据或资料什么的,并没有什么WWW万维网和花花绿绿的网页。
,属于应用层协议,凌驾于TCP(传输控制协议)和IP(网络协议)之上。
后两者属于传输层和网络层。传输层位于网络层之上。
网络层的再下一层是连链接层,主要是wifi,光纤灯物理设备的驱动协议,实现与底层硬件的连接和控制。
最下一层就是物理层,也就是wifi,光纤,以太网,路由器等硬件物理设备。
以上就是网络协议的五层模型
,
就是与五层网络模型配套的各层网络协议包。此外还有基于OSI模型的七层网络模型
就是传输网络信息的层层打包。
网络应用基于网络信息的传输,实现客户端与服务器之间的互动。
位于最高层的应用发出书面指示。而最底层的硬件就是快递员,负责把这封信给送出去。
为了实现某一功能,某服务器的网络应用层(比如nodemcu)要向客户端(比如手机上的浏览器)发送一串信息,指定信息属于HTTP协议。
信息被应用层打包,信息前加上应用层的标签信息,明确属于哪种包裹(应用层协议除了HTTP,还有FTP,SMTP...)
传输层接到应用层指示,在客户端和服务器之间开辟一条传输通道,它把很长的信息打包成一小段小一段,并且有一整套的校验机制,确保信息可靠发送。
数据分割后二次打包,头部附上响应传输层标签,明确快递收件人和寄件人,确定了快递路线,控制寄件时间,并且监督快递安全送达
网络层接到传输层指示,负责把数据从发送端传输到接收端。发送端和接收到都有唯一的IP地址,就像快递收件地址和寄件地址。
信息三次打包,加上IP信息,明确收货地址和寄件地址
有了收件地址和寄件地址,就需要这两个地址派快递员送信,就是服务器nodemcu的wifi设备和客户端(手机)的wifi设备。
数据四次打包,加上客户端和服务端的wifi硬件信息,明确谁是快递员。
上述手续办完之后,快递员(硬件设备)会忠于职守,把快递送达。
lua固件提供了对各层网络协议的支持,底层协议不用我们关心。我们要关注的是应用层的协议,或者再下一层的传输层协议。
应用层HTTP是基于传输层TCP协议的。与TCP传输一样,HTTP也分为客户端和服务器端,这里特指nodemcu作为HTTP的客户端和服务器。
lua固件中有现成的HTTP客户端模块,对于服务器端,大部分需要自己编写。接下来,我们就看一个HTTP服务器例程。
固件文件夹中的HTTP示例程序我没有调试通过,因此我参考的是另一个版本的服务器程序,程序包可以点这里下载,文件名是dht11_webserver.lua
。
为了介绍HTML,HTTP和TCP协议,我对原代码进行了修改
- 示例程序是用TCP/IP协议实现的HTTP服务器,在电脑和手机的浏览器里输入nodemcu的IP地址,就可以进入服务器
- 本服务器网页,也就是HTML文件,包括三个部分:标题,图片和段落。每刷新一次,服务器返回nodemcu当前剩余的内存
- 服务器代码如下,文件名为LUAserver.lua
-- LUA Webserver --
dofile("import_image.lua")
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print("Heap = "..node.heap().." Bytes")
print("Print payload:\n"..payload)
-- write HTML
head = "ESP8266 Webserver "
body = "Welcome to Nodemcu
"
para = "The size of the memory available: "
..tostring(node.heap()).." Bytes "
image1 = "..png1
image2 = png2.."\" width = \"50\" height = \"50\" />"
ending = ""
reply1 = head..body..image1
reply2 = image2..para..ending
payloadLen = string.len(reply1) + string.len(reply2)
conn:send("HTTP/1.1 200 OK\r\n")
conn:send("Content-Length:" .. tostring(payloadLen) .. "\r\n")
conn:send("Connection:close\r\n\r\n")
conn:send(reply1)
conn:send(reply2)
collectgarbage()
end)
conn:on("sent",function(conn)
conn:close()
end)
end)
下面对代码进行解释
程序第八行(算上注释)-- write HTML
以下的内容,到空白行为止
head..
HTML文件以开始,
结束。文件开头要有
,
之后的第一部分是head,以开始,
结束。这里用来确定标题title
title的格式是
,title的内容ESP8266 Webserver
会显示在网页的标签上
body..
body部分是HTML的主体,同样以开始,
结束
代表第一个标题,格式是
...<\h1>
para..
标题以下是段落部分,以开始,
这里要显示nodemcu的剩余内存大小,用函数node.heap()得到数值,并用tostring()转换成字符串,再用..
将前后的字符串连成一体
image1..
,image2..
是HTML插入的图像,本来是一句,因为太大分成了两部分。
最简单格式为,XX.XX代表图像名和后缀,比如
nodmcu.png
,图片文件通常和HTML文件放在一起,或放在专门的文件夹。
nodemcu文件系统中,并没有存放HTML文档。而发送的HTML是作为代码内嵌在程序中。
同样,图像文件也作为代码内嵌到程序中.我们可以将png等图像文件转换成base64编码,图像文件用很长的字符串表示。
在另一个lua文件import_image.lua
中,我们定义了图像的base64字符串png1和png2.文件有1k多,太大所以分成了两个。当本程序执行时,首先dofile(“import_image.lua”),得到图像字符串
结尾处的width = \"50\" height = \"50\"
定义图像的大小,50两边"
前要加转义符/
,否则编译会报错
end..
部分用和