5. ネットワーク - TCPソケット¶
ほとんどのインターネットの構成要素は TCP ソケットです。これらのソケットは、接続されたネットワークデバイス間で信頼できるバイトストリームを提供します。チュートリアルのこの部分では、いくつかの異なるケースで TCP ソケットを使用する方法を示します。
5.1. スターウォーズのテキストアニメーション¶
最も簡単なことは、インターネットからデータをダウンロードすることです。ここでは、blinkenlights.nl のウェブサイトで提供されているスターウォーズのアシメーションサービスを使用します。これは、ポート 23 上の Telnet プロトコルを使用して、接続するすべての人にデータをストリーミングします。認証する必要がない(ユーザー名またはパスワードを入力する必要がない)ので、データのダウンロードをすぐに開始できで、使い方が簡単です。
最初に行うことは、使用可能なソケットモジュールがあることを確認することです。
>>> 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 を使って、このコードを試してみることもできます。
5.2. HTTP GETリクエスト¶
次の例は、Web ページをダウンロードする方法を示しています。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')
これにより、Webページが取得され、HTMLがコンソールに出力されます。
5.3. シンプルなHTTPサーバー¶
次のコードは、すべての GPIO ピンの状態を示す表を含む単一の Web ページを提供する単純な HTTP サーバーを作成します。
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('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('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()