5. Network - TCP sockets¶
大多数互联网的基本组件即为TCP socket。这些sockets提供了相连的网络设备间的可靠字节流。本教程的此章节将演示在不同情况下如何使用TCP socket。
5.1. Star Wars Asciimation¶
最简单的事情就是从网上下载数据。在这种情况下,我们将使用由blinkenlights.nl网站提供的Star Wars Asciimation设备。 其使用端口23上的远程登录协议来向任何与之相连的设备传输流数据。使用方法很简单,因为并不需要您进行鉴别(给定一个用户名或密码),您可直接开始下载数据。
首先,确保我们的socket模块可用:
>>> import socket
然后获取服务端的IP地址:
>>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
实际上,getaddrinfo
函数会返回一个地址列表,且每个地址的信息都超出我们的需要。
我们只想获取首个有效地址和服务端的IP地址和端口。使用以下指令来完成这一步骤。
>>> addr = addr_info[0][-1]
若您在提示框中输入 addr_info``和 ``addr
,您看到的就是其中包含的信息。
使用IP地址,我们可以制作一个socket并连接到服务端:
>>> s = socket.socket()
>>> s.connect(addr)
我们已建立连接,所以可下载和显示数据:
>>> while True:
... data = s.recv(500)
... print(str(data, 'utf8'), end='')
...
当此循环执行时,应开始动了(使用ctrl-C可中断)。
若您想尝试一下,您也可以使用常规Python在个人电脑上运行这一代码。
5.2. HTTP GET 请求¶
下一个示例演示如何下载网页。HTTP端口使用端口80,下载前,您首先需要发送”GET”请求。在该请求中,您应指定检索的页面。
我们来定义一个可下载和打印URL的函数:
def http_get(url):
_, _, host, path = url.split('/', 3)
addr = socket.getaddrinfo(host, 80)[0][-1]
s = socket.socket()
s.connect(addr)
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
s.close()
确保您在运行此函数之前输入socket模块。然后您可尝试:
>>> http_get('http://micropython.org/ks/test.html')
此指令应检索页面并将HTML打印到控制台。
5.3. 简单的 HTTP 服务器¶
下列代码创建一个简易HTTP服务器,该服务器只提供包含所有GPIO引脚的状态的列表的页面::
import machine
pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)]
html = """<!DOCTYPE html>
<html>
<head> <title>ESP32 Pins</title> </head>
<body> <h1>ESP32 Pins</h1>
<table border="1"> <tr><th>Pin</th><th>Value</th></tr> %s </table>
</body>
</html>
"""
import socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('listening on', addr)
while True:
cl, addr = s.accept()
print('client connected from', addr)
cl_file = cl.makefile('rwb', 0)
while True:
line = cl_file.readline()
if not line or line == b'\r\n':
break
rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins]
response = html % '\n'.join(rows)
cl.send(response)
cl.close()