易讯联教您用单片机实现HTTP网页服务器功能发表时间:2020-10-09 17:14 一、通过浏览器向单片机发送请求 在浏览器输入socket地址后,可以在串口助手上看到以下数据:(以下数据均为字符) //------------------------------------------------ GET / HTTP/1.1 //------------------------------------------------ 这就是浏览器向服务器发送的请求数据(不同浏览器的数据稍有不同) 在这里我们只关心第一行,这行数据表明,浏览器向单片机请求网页。这是浏览器第一次请求的命令,若需要请求其他网页,第一行可能会变成: GET /xxxx.HTML HTTP/1.1,这时,只要判断此处的信息,就可以知道该发送哪个网页给浏览器。 三、单片机返回相应网页数据包 假设收到浏览器第一次发送的请求“GET / HTTP/1.1”,此时浏览器和网络模块的socket已经建立连接,并等待数据返回。 我们通过相应socket向浏览器返回一个登陆界面 Login.HTML的代码:(下文相同代码均用(网页代码1)等方式表示) (网页代码1) //------------------------------------------------ <!DOCTYPE html> //------------------------------------------------ 因为单片机的储存空间有限,一般将网页以const的形式存放在flash中,而且尽量精简,除了必要的效果和兼容性语句外, 其他都可以删掉(如对齐格式时使用的大量tab、空格等),以减轻单片机负担。但是为了编写网页方便,建议将网页源文件复制粘贴到别处,删除多余的内容后再烧写到单片机中。 好了,接着上面的说,真的只发一个网页过去就行了吗? 当然了,肯定不行。因为浏览器无法知道单片机要发送什么类型、多少长度的数据。所以,我们还需要一个返回数据的格式。 //------------------------------------------------ HTTP/1.1 200 OK //------------------------------------------------ 文章1`2中也已经讲到了。所以,我们发送到浏览器的数据应该是这样的: //------------------------------------------------ HTTP/1.1 200 OK //------------------------------------------------ 注意,这些数据中,有些换行是不能省的(下文\r\n起强调作用,并不是接收到的字符): //------------------------------------------------ HTTP/1.1 200 OK\r\n //------------------------------------------------ 否则浏览器无法识别数据。 其中的Content-Length:282是网页文件的大小(字节),需要提前算好。这样,浏览器收到了第一个网页,显示效果如下。 不管其他的,我们先登陆一下试试,输入用户名:hello,密码:world,点击登录。然后我们发现单片机收到了如下数据: //------------------------------------------------ GET /Login.cgi?Username=hello&Password=world HTTP/1.1 //------------------------------------------------ 好了,我们需要的数据应该全在第一行里面了,有用户名和密码,但是看一下浏览器的地址栏,用户名和密码同样以URL的形式出现了: //------------------------------------------------ HTTP://192.168.1.199/Login.cgi?Username=hello&Password=world //------------------------------------------------ 知道了get 和 post 的区别,我们将Login.html中 method='get' 改为 method='post'重新操作一次,结果,单片机收到的数据变成了这样: //------------------------------------------------ POST /Login.cgi HTTP/1.1 //------------------------------------------------ 以此方法,其他网页也可以发送到浏览器并返回单片机所需要的数据。 四、通过JS让网页活起来 现在让我们先做一个设置单片机串口的网页,并通过网页更新单片机串口设置。网页代码如下 (网页代码2) //------------------------------------------------ <!DOCTYPE html> //------------------------------------------------ 先看一下效果: 串口的设置是在变的,不能写死到网页里,该怎么动态显示呢? 当然,这种时候少不了Javascript。在网页的最后追加几句话: (网页代码3) //------------------------------------------------ <script> //------------------------------------------------ value里的值是通过单片机实时生成的,我们姑且这样写。发送一下试试先: //------------------------------------------------ HTTP/1.1 200 OK //------------------------------------------------ 现在,显示效果是这样的: 这样,我们完成了单片机内部参数在网页上显示的效果。 得陇望蜀,人之常情,做完串口配置,又想把所有的单片机配置全部用网页完成,结果做出来一个比较大的网页。 这个网页上需要显示很多的值,需要动态生成很多的JS语句,如果采用Content-Length这种固定长度的方式发送,该怎么计算网页长度呢? 当然,可以一句一句用strlen计算加上去,再更改Content-Length的值。 然而这种方式很麻烦,不好操作(因为网页是const类型),有时候网页的长度根本没办法预知,会导致网页发送失败,浏览器打不开网页。 实际上,这种问题当然是可以完全解决的。 五、灵活的网页传输方式 我们在上网的时候,实际上大部分的网页是动态的,不能预知长度,那么这些网页是怎么正确传输到浏览器上的呢? 如果你有TCP/IP的抓包软件,在抓到的数据包中,可能会看到这样一句: Transfer-Encoding: chunked 这句话的意思是:不定长发送,即每个数据包中规定此包数据的大小,等待发送完成后,再发送一个结束符。 这样浏览器就不必知道整个网页有多大,只要等结束符就行。 具体操作方式是这样的: //------------------------------------------------ HTTP/1.1 200 OK\r\n //------------------------------------------------ 那么再试一试上面的网页: //------------------------------------------------ HTTP/1.1 200 OK\r\n //------------------------------------------------ 如果想向网页中添加数据,只要在结束符之前发送就OK。 现在,最基本的功能都实现了,但是,网页看起来有点丑,还能再给力点吗? 通过CSS格式,可以做出很多炫酷的网页特效,但是有些效果,还是不能代替图片。那么,看下一节: 六、图片,让网页绚丽多彩。 是的,少了图片的网页,看起来枯燥无味。那么,让我们尝试着发送一张图片到浏览器上去。 首先,需要把图片存入单片机,在百度中搜索“任意文件转C语言数组”,用这个小工具,把图片先转换成十六进制数组。 |