MicroPython:Платы/ESP8266/Руководство по MicroPython для ESP8266/Сеть – TCP-сокеты
Сеть – TCP-сокеты[1]
TCP-сокеты – это строительные кирпичики большей части интернета. Благодаря этим сокетам осуществляется надежный поток байтов между подключенными друг к другу сетевыми устройствами. В этой части руководства мы покажем несколько разных примеров использования этих TCP-сокетов.
Star Wars Asciimation
Самое простое, что можно сделать – это загрузить данные из интернета. Мы воспользуемся для этого сервисом Star Wars Asciimation, который можно найти на сайте blinkenlights.nl. Он использует протокол TELNET на порте 23, чтобы передавать данные любому, кто к нему подключится. Его очень легко использовать, потому что он не требует аутентификации (вам не нужно будет писать имя или пароль) – вы можете сразу начинать загружать данные.
Во-первых, надо убедиться, есть ли у вас модуль socket:
>>> import socket
Затем нужно узнать IP-адрес сервера:
>>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
Функция getaddrinfo() вернет список адресов, но каждый адрес будет содержать избыточную и не нужную нам информацию. Нам лишь нужен первый корректный адрес, а затем лишь IP-адрес и порт сервера. Чтобы сделать это, впишите следующее:
>>> addr = addr_info[0][-1]
Если вписать addr_info и addr в командную строку, вы увидите, какая информация в них хранится.
При помощи IP-адреса мы можем создать сокет и подключиться к серверу:
>>> s = socket.socket()
>>> s.connect(addr)
Теперь, подключившись, мы можем загрузить и показать данные:
>>> while True:
... data = s.recv(500)
... print(str(data, 'utf8'), end='')
...
Когда этот цикл будет выполнен, он должен начать показывать анимацию (чтобы прервать ее, нажмите Ctrl + C ).
Вы также можете запустить этот же самый код на своем ПК при помощи обычного Python (если у вас есть желание попробовать его там).
Запрос HTTP GET
В этом примере мы покажем, как загрузить веб-страницу. Протокол HTTP использует порт 80 и перед тем, как что-нибудь загрузить, вам надо будет отправить запрос GET. В этом запросе вам также надо будет указать страницу, которую нужно извлечь.
Давайте зададим функцию, способную загрузить и напечатать URL:
def http_get(url):
import socket
_, _, 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()
Затем попробуйте следующее:
>>> http_get('http://micropython.org/ks/test.html')
В результате эта функция должна скачать веб-страницу и напечатать в консоли ее HTML-код.
Простой 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>ESP8266 Pins</title> </head>
<body> <h1>ESP8266 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('прослушиваем', addr)
while True:
cl, addr = s.accept()
print('клиент подключился от', 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('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()