9.11. ソケットオブジェクト

トランスポート層へのPythonインターフェースは socket.socket クラスです。ソケット はネットワーク上の会話の一方の端点、すなわちアドレス、ポート、そしてその会話が動作するプロトコル(UDPまたはTCP)を表します。ハードウェア制御の章では UART インスタンスを開いて配線上で通信しました。このセクションでは socket インスタンスを開いてネットワーク上で通信します。形は同じで、基盤となるサービスがはるかに高機能なだけです。

9.11.1. ソケットの作成

ソケットを記述するのは3つの引数です。どの アドレスファミリー を話すか、どの ソケットタイプ を提供するか、そしてどの プロトコル を使うかです。デフォルト値は、このセクションの残りで使うケースをカバーしています:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)   # IPv4 TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    # IPv4 UDP

アプリケーションがほぼすべてのケースで選択する2つの定数は次のとおりです。

  • AF_INET -- IPv4アドレス(数値IPとポート)。最も一般的な選択です。AF_INET6 はIPv6の同等物です。

  • SOCK_STREAM -- TCP接続、信頼性のあるバイトストリームです。SOCK_DGRAM はUDPの同等物です。

3番目の引数(プロトコル)はゼロのままにしておきます。これは最初の2つに基づいて適切なデフォルトを選びます。完全なコンストラクタは socket --- socket モジュール に記載されています。

9.11.2. ソケット上のアドレス

ソケットアドレスは (host, port) のタプルです:

("192.168.1.50", 80)
("0.0.0.0", 8000)

hostは文字列としてのIPアドレスです。portは ポート で扱った16ビット整数です。

知っておく価値のある 特別な host文字列がいくつかあります。

  • "0.0.0.0" は「このデバイス上のすべてのIPv4インターフェース」を意味します。このアドレスにバインドされたサーバーは、カメラが持つどのアドレス上でも接続を受け付けます。

  • "127.0.0.1"localhost です。そこへのトラフィックはデバイスから決して出ません。テストに便利です。

  • "255.255.255.255" はローカルブロードキャストアドレスです。そこへ送られたUDPデータグラムは、ローカルセグメント上のすべてのデバイスへ届きます。

"example.com" のようなドメイン名は、ソケットアドレスの有効なhost文字列では ありません。まずIPに解決する必要があります。名前と DNS がそれを行う getaddrinfo() 呼び出しを扱います。

9.11.3. 2つの役割

ソケットのライフサイクルは、それが会話のどちら側にあるかによって決まります。クライアント ソケットは既知のサーバーと通信するために connect()(UDPの場合は単に sendto())を呼び出します。サーバー ソケットはポートを確保するために bind() を呼び出し、その後、受信トラフィックを受け取るために listen()accept()(TCPの場合)または recvfrom()(UDPの場合)を呼び出します。

どちらの場合も同じ socket コンストラクタが使われ、その後に呼び出すメソッドだけが異なります。続く3つのページで実用的なパターンを順に見ていきます。

9.11.4. ソケットのクローズ

すべてのソケットは、オペレーティングシステムの状態の小さな一片(ポートの予約、バッファ、接続のTCP状態)を保持しています。アプリケーションがそれを使い終えたら、close() がその状態を解放します。忘れられたソケットは積み重なる緩やかなリークです。接続を開くループでは、close を忘れると最終的にカメラの利用可能なソケットのプールを使い果たしてしまいます。

最もきれいなパターンは with 文です:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(addr)
    s.send(b"GET / HTTP/1.0\r\n\r\n")
    ...
# socket is closed automatically here, even on error

ソケットはPython概要で扱われたコンテキストマネージャプロトコルを実装しているため、with ブロックは、ブロックが正常に終了したか例外を送出して終了したかにかかわらず、close() が呼び出されることを保証します。

9.11.5. socket リファレンス

このページと続くページではAPIを物語形式で順に見ていきます。すべてのメソッド、すべてのフラグ、モジュールが公開するすべての定数の引数レベルの完全なリファレンスについては、socket --- socket モジュール を参照してください。このセクションが扱わない、あまり一般的でない操作(ソケットオプション、マルチキャストグループのメンバーシップ、IPv6スコープID)を調べる場所もリファレンスです。