目的
WebServer是非常常用的一个功能,在设备上使用该功能用户就可以不依赖app直接通过浏览器访问和操作设备。另外即使是用app的,对于app开发来说直接访问webapi也比处理tcp/udp要方便些。本文将简单介绍使用基于TCP的socket编程来实现WebServer功能。
WebServer基础说明
WebServer主要是用作对客户端发出的基于HTTP协议的请求进行响应(比如用户通过浏览器输入某个网址进行访问的时候就会向该地址发送请求头)。请求头示例如下:
GET / HTTP/1.1
Host: www.baidu.com
Connection: close
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
上面的一段字符串就是一个请求头(注意最后的空行),该请求请求访问百度首页,百度的服务器收到该请求后就返回 响应头
和 所请求的内容
。
上面的请求头其实就是个字符串,字符串中包含特定内容和格式(这就是HTTP协议所规定的),这个字符串通过TCP方式进行传输,所以我们可以用TCP方式的socket编程实现WebServer功能。
WebServer使用演示
基础实现演示
下面是个通过TCP方式的socket编程实现WebServer功能的简单演示:
import network
import usocket as socket # 引用socket模块
# 响应头
responseHeaders = b'''
HTTP/1.1 200 OK
Content-Type: text/html
Connection: close
'''
# 响应头网页正文内容
content = b'''
Hello World!
'''
ap = network.WLAN(network.AP_IF)
ap.config(essid='lalala', authmode=4, password='12345678')
ap.active(True) # 开启无线热点
def main():
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (重要)设置端口释放后立即就可以被再次使用
s.bind(socket.getaddrinfo("0.0.0.0", 80)[0][-1]) # 绑定地址
s.listen(5) # 开启监听(最大连接数5)
print('接入热点后可从浏览器访问下面地址:')
print(ap.ifconfig()[0])
print('')
while True: # mian()函数中进行死循环,在这里保持监听浏览器请求与对应处理
client_sock, client_addr = s.accept() # 接收来自客户端的请求与客户端地址
print('Client address:', client_addr)
while True:
h = client_sock.readline() # 按行读取来自客户端的请求内容
print(h.decode('utf8'), end='')
if h == b'' or h == b'\r\n': # 当读取到空行的时候表示接收到一个完整的请求头
break
client_sock.write(responseHeaders) # 向客户端发送响应头
client_sock.write(content) # 向客户端发送网页内容
client_sock.close()
main() # 运行main()函数
上面例子中我开启了TCP监听,然后通过浏览器访问时就可以收到来自浏览器的请求,代码中逐行读取请求内容,在读取到空行后当作请求完整,然后向浏览器发送了响应头和网页内容。
在上面例子中没有检查请求的内容,实际使用中需要解析请求内容,在根据请求的内容进行响应(比如通过浏览器请求控制某个IO口来驱动LED等等功能)。
通过浏览器控制设备
WebServer最实用的功能就是通过浏览器获取或控制电路的状态了,下面例子进行了简单的演示:
import network
from machine import Pin
import usocket as socket # 引用socket模块
ap = network.WLAN(network.AP_IF)
ap.config(essid='lalala', authmode=4, password='12345678')
ap.active(True) # 开启无线热点
led = Pin(13, Pin.OUT, value=0) # 初始化LED管脚,低电平点亮
def main():
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (重要)设置端口释放后立即就可以被再次使用
s.bind(socket.getaddrinfo("0.0.0.0", 80)[0][-1]) # 绑定地址
s.listen(5) # 开启监听(最大连接数5)
print('接入热点后可从浏览器访问下面地址:')
print(ap.ifconfig()[0])
print('')
while True: # mian()函数中进行死循环,在这里保持监听浏览器请求与对应处理
client_sock, client_addr = s.accept() # 接收来自客户端的请求与客户端地址
q = ''
while True:
h = client_sock.readline() # 按行读取来自客户端的请求内容
q += h.decode('utf8')
if h == b'' or h == b'\r\n': # 当读取到空行的时候表示接收到一个完整的请求头
break
if q.startswith('GET / HTTP/1.1'): # 从浏览器访问 /
client_sock.write('led is on' if(not led.value()) else 'led is off') # 向客户端发送内容
elif q.startswith('GET /on HTTP/1.1'): # 从浏览器访问 /on
led.off() # 低电平点亮led
client_sock.write('led turn on') # 向客户端发送内容
elif q.startswith('GET /off HTTP/1.1'): # 从浏览器访问 /off
led.on() # 高电平关闭led
client_sock.write('led turn off') # 向客户端发送内容
else:
client_sock.write('not found') # 向客户端发送内容
client_sock.close()
main() # 运行main()函数
上面例子中通过浏览器访问不同链接,WebServer检索请求头内容分别给出不同应答。
更多内容可以参考我别的博文:
《从零开始的ESP8266探索(06)-使用Server功能搭建Web Server》
第三方WebServer库介绍
实际使用中如果用上面的方式处理,如果遇到大型的项目就显得麻烦了,这时候可以尝试使用人家写好的WebServer库,这里介绍一些:
-
MicroWebSrv
这个库注意用于MicroPython,总共就三个文件,分别提供了WebServer基本功能、WebSocket、模板支持。MicroWebSrv is a micro HTTP Web server that supports WebSockets, html/python language templating and routing handlers, for MicroPython (principally used on ESP32 and Pycom modules. Now supports all variants of Pyboard D-series from the makers of Micropython)
项目地址:https://github.com/jczic/MicroWebSrv
-
MicroWebSrv2
这个库功能更加全面,性能上也更好,不过库的大小和内存占用也更加高了,基本上不带外部SPI RAM的ESP32模块都别想好好跑。这个库不仅持MicroPython,还支持标准的CPython。MicroWebSrv2 is the new powerful embedded Web Server for MicroPython and CPython that supports route handlers, modules like WebSockets or PyhtmlTemplate and a lot of simultaneous requests (in thousands!).
Fully asynchronous, its connections and memory management are very optimized and truly fast.
Mostly used on Pycom WiPy, ESP32, STM32 on Pyboard, … Robust and efficient!项目地址:https://github.com/jczic/MicroWebSrv2
总结
WebServer是一个常用的功能,MicroPython上想要用也不麻烦,更多内容除了可以参考上面第三方的库,也可以参考官方的例程。MicroPython官方的WebServer例程可以在下面链接中找到:
https://github.com/micropython/micropython/tree/master/examples/network