socket -- ソケットモジュール

このモジュールは、該当する :term:`CPython` モジュールのサブセットを実装しています。 詳しくはオリジナルの CPython ドキュメンテーションを参照してください: socket.

このモジュールは BSD ソケットインタフェースへのアクセスを提供します。

CPython との違い

効率性と一貫性のために、MicroPython のソケットオブジェクトは stream (ファイルライク)インタフェースを直接実装します。CPythonでは makefile() メソッドを使ってソケットをファイルライクなオブジェクトに変換する必要があります。この方法は MicroPython でもサポートされています(ただし何もしません)ので、CPython との互換性が重要な場合は必ず使ってください。

ソケットアドレスフォーマット

socket モジュールのネイティブなソケットアドレスフォーマットは getaddrinfo 関数によって返される不透明なデータ型です。 getaddrinfo は、テキストアドレス(数値アドレスを含む)を解決するために使う必要があります。

sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 数値アドレスでも getaddrinfo() を使う必要があります
sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1]
# これでアドレスを使えるようになります
sock.connect(addr)

getaddrinfo を使うことは(メモリと処理能力の両方の点で)最も効率的で、アドレスを扱うための移植性のある手段です。

ただし socket モジュール(ここで説明しているネイティブ MicroPython の socket との違いに注意)は後述するように、タプルを使ってアドレスを指定する CPython 互換の手段を提供します。 MicroPython ポート により、 socket モジュールは組込み済なこともありますし、(MicroPython Unix port の場合のように) micropython-lib からインストールが必要なこともあります。ポートによってはタプルフォーマットの数値アドレスのみしか受け付けられないこともありますし、ドメイン名を解決するために getaddrinfo 関数を使うことが必要なこともあります。

まとめると:

  • 移植性のあるアプリケーションを書くには getaddrinfo を必ず使ってください。
  • 後述するタプルアドレスは、それがサポートされているなら、クイックハックや対話的な利用のためのショートカットとして使えます。

socket モジュールのタプルアドレスフォーマット

  • IPv4: (ipv4_address, port) -- ipv4_address はドット表記の数値の IPv4 アドレスを持つ文字列で、たとえば "8.8.8.8" などです。 port は 1〜65535 の範囲の整数のポート番号です。ドメイン名は ipv4_address として受け入れられないので、socket.getaddrinfo() を使って事前に解決しておくよう注意してください。
  • IPv6: (ipv6_address, port, flowinfo, scopeid) -- ipv6_address はコロン表記の数値の IPv6 アドレスを持ち文字列で、たとえば "2001:db8::1[" などです。 port は 1〜65535 の範囲の整数のポート番号です。 flowinfo は 0 にする必要があります。 scopeid はリンクローカルアドレスのインターフェイススコープ ID です。ドメイン名は ipv6_address として受け入れられないので、 socket.getaddrinfo() を使って事前に解決しておくよう注意してください。IPv6 サポートの可用性は MicroPython ポート に依存します。

関数

socket.getaddrinfo(host, port, af=0, type=0, proto=0, flags=0, /)

host/port 引数を、そのサービスに接続されたソケットを作成するために必要となるすべての引数を含む一連の5項目のタプルに変換します。引数 af, type, proto (これらは socket() 関数の場合と同じ意味を持つ)を使って、返されるアドレスの種類をフィルタ処理できます。パラメータが指定されていないかゼロの場合、アドレスのすべての組み合わせを返すことができます(利用者側でのフィルタリングが必要です)。

結果として得られる5項目のタプルは次のの構造を持ちます:

(family, type, proto, canonname, sockaddr)

次の例は特定の URL に接続する方法を示しています:

s = socket.socket()
# これは "type" が指定されていない場合、SOCK_STREAM のアドレスが返される
# ことを前提としています。これは正しくない可能性があります
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])

フィルタリングパラメータの推奨の使用法は次のとおりです:

s = socket.socket()
# ストリーム操作のために接続できるアドレスを返すことが保証されています。
s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])

CPython との違い

この関数でエラーが発生した場合、CPython は socket.gaierror 例外(OSError のサブクラス)を発生させます。MicroPython には socket.gaierror がなく、 OSError を直接発生させます。 getaddrinfo() のエラー番号は別の名前空間を形成していて、 errno モジュールのエラー番号と一致しない場合があることに注意してください。 getaddrinfo() のエラーは負の数で表され、正の数である標準のシステムエラーと区別できます(エラー番号には例外オブジェクトの e.args[0] プロパティを使ってアクセスできます)。負の値の使用は暫定的な処置であり、将来変更される可能性があります。

socket.inet_ntop(af, bin_addr)

指定したアドレスファミリ af のバイナリ形式ネットワークアドレス bin_addr をテキスト表現に変換します。

>>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'
socket.inet_pton(af, txt_addr)

指定したアドレスファミリ af のテキスト形式のネットワークアドレス txt_addr をバイナリ表現に変換します。

>>> socket.inet_pton(socket.AF_INET, "1.2.3.4")
b'\x01\x02\x03\x04'

定数

socket.AF_INET
socket.AF_INET6

アドレスファミリタイプ。可用性は特定の MicroPython ポート に依存します。

socket.SOCK_STREAM
socket.SOCK_DGRAM

ソケットタイプ。

socket.IPPROTO_UDP
socket.IPPROTO_TCP

IP プロトコル番号。可用性は特定の MicroPython ポート に依存します。 socket.socket() の呼び出しに指定する必要がないことに注意してください。なぜなら SOCK_STREAM では IPPROTO_TCPSOCK_DGRAM では IPPROTO_UDP のソケットタイプが自動的に選択されるからです。したがって、これらの定数の唯一の実際に使うのは setsockopt() の引数としてです。

socket.SOL_*

ソケットオプションレベル(setsockopt() の引数)。何があるかは MicroPython ポート に依存します。

socket.SO_*

ソケットオプション(setsockopt() の引数)。何があるかは MicroPython ポート に依存します。

WiPy に固有の定数:

socket.IPPROTO_SEC

SSL 互換ソケットを作成するための特別なプロトコル値。

クラス socket

class socket.socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /)

指定したアドレスファミリ、ソケットタイプ、プロトコル番号を使って新しいソケットを作成します。ほとんどの場合 proto を指定する必要はありません(MicroPython の一部のポートでは IPPROTO_* 定数が省略されている場合があるため、指定はお勧めしません)。代わりに type 引数が必要なプロトコルを自動的に選択します。

# STREAM TCP ソケットを作成
socket(AF_INET, SOCK_STREAM)
# DGRAM UDP ソケットを作成
socket(AF_INET, SOCK_DGRAM)

メソッド

socket.close()

ソケットを閉じられたものとしてマークし、すべてのリソースを解放します。これを呼び出すと、このソケットオブジェクトに対する操作はすべて失敗します。プロトコルでサポートされている場合、リモート側の端点は EOF 通知を受け取ります。

ソケットはガベージコレクション時に自動的にクローズされますが、作業を終えたらすぐに close() を明示的に呼び出すことを勧めます。

socket.bind(address)

ソケットをアドレス address にバインドします。バインド済みのソケットを再バインドする事はできません。

socket.listen([backlog])

サーバーが接続を受け付けるようにします。バックログ backlog が指定されている場合、少なくとも 0 以上でなければなりません(それより低い場合 0 に設定されます)。バックログは、システムが新しい接続を拒否するまでに許可する未受付の接続の数を指定します。指定しない場合、デフォルトの妥当な値が選択されます。

socket.accept()

接続を受け入れます。ソケットはアドレスにバインド済みで、接続を待機(listen)している必要があります。戻り値は (conn, address) のペアです。conn は接続を通じてデータの送受信を行うための新しいソケットオブジェクト、address は接続先でソケットにバインドしているアドレスです。

socket.connect(address)

アドレス address でリモートソケットに接続します。

socket.send(bytes)

ソケットにデータを送信します。ソケットはリモートソケットに接続済みでなければなりません。戻り値として、送信したバイト数を返します。これはデータの長さより短い場合があります(「短い書き込み」")。

socket.sendall(bytes)

ソケットにすべてのデータを送信します。ソケットはリモートソケットに接続済みでなければなりません。 send() と異なり、このメソッドはデータをチャンク単位で連続して送信することによって、すべてのデータを送信しようとします。

非ブロッキングソケットでのこのメソッドの動作は未定義です。このため MicroPython では、代わりに write() の利用を勧めます。これは、ブロッキングソケットと同じ「短い書き込み禁止」ポリシーを持ち、非ブロッキングソケットで送信されたバイト数を返します。

socket.recv(bufsize)

ソケットからデータを受信します。戻り値は受信したデータを表すバイト列オブジェクトです。一度に受信するデータの最大量は bufsize で指定します。

socket.sendto(bytes, address)

ソケットにデータを送信します。このメソッドでは接続先を address で指定するので、ソケットがリモートソケットに接続済みではいけません。

socket.recvfrom(bufsize)

ソケットからデータを受信します。戻り値は (bytes, address) のペアです。 bytes は受信データを表すバイト列オブジェクトで、 address はデータを送信するソケットのアドレスです。

socket.setsockopt(level, optname, value)

指定されたソケットオプションの値を設定します。必要なシンボリック定数は、socket モジュール(SO_* など)で定義されています。 value は整数、None、またはバッファを表すバイト列ライクなオブジェクトのいずれかです。

socket.settimeout(value)

注記注: すべてのポートがこのメソッドをサポートしているわけではありません。下記を参照してください。

ブロッキングソケットの操作のタイムアウト値を指定します。 value 引数には負でない浮動小数点数値で表した秒数を指定するか、None を指定します。ゼロ以外の値を指定した場合、ソケット操作が完了する前にタイムアウト期間が経過した場合、 OSError 例外が発生します。ゼロを指定した場合、ソケットは非ブロッキングモードになります。None を指定した場合、ソケットはブロックモードになります。

すべての MicroPython ポート がこのメソッドをサポートしているわけではありません。よりポータブルで汎用的な解決策は select.poll オブジェクトを使うことです。これにより、複数のオブジェクトを同時に待機することができます(ソケットだけでなく、ポーリングをサポートする汎用の stream オブジェクトも対象になります)。たとえば次のように使います:

# settimeout を使う場合:
s.settimeout(1.0)  # タイムアウトを秒数で指定
s.read(10)  # タイムアウトが発生する可能性あり

# 代わりの使用例:
poller = select.poll()
poller.register(s, select.POLLIN)
res = poller.poll(1000)  # タイムアウトをミリ秒で指定
if not res:
    # s から入力されなくなったということは、操作がタイムアウトしている

CPython との違い

CPython はタイムアウトの場合に socket.timeout 例外を発生させます。この例外は OSError のサブクラスです。MicroPython は代わりに OSError を直接発生させます。例外を捕らえるのに except OSError: を使えば、コードは MicroPython と CPython の両方で動作します

socket.setblocking(flag)

ソケットをブロッキングモード、または非ブロッキングモードに設定します。flag が False の場合にはソケットは非ブロッキングモードになり、True の場合にはブロッキングモードになります。

このメソッドは、次の settimeout() 呼び出しの省略形です:

  • sock.setblocking(True)sock.settimeout(None) と等価です
  • sock.setblocking(False)sock.settimeout(0.0) と等価です
socket.makefile(mode='rb', buffering=0, /)

ソケットに関連したファイルオブジェクトを返します。戻り値の正確な型は makefile()に指定した引数によります。サポートはバイナリモード('rb', 'wb', 'rwb')のみに限定されています。CPython の引数: "encoding, errors and newline はサポートされていません。

CPython との違い

MicroPython はバッファ付きストリームをサポートしていないため、 buffering パラメータの値は無視され、0 (バッファなし)のように扱われます。

CPython との違い

makefile() から返されたファイルオブジェクトを閉じると、元のソケットも閉じられます。

socket.read([size])

ソケットから size バイトまで読み込みます。戻り値はバイト列オブジェクトです。 size が与えられていない場合、EOF までソケットから利用可能なすべてのデータを読み込みます。そのため、 size を指定しないメソッド呼出しはソケットが閉じられるまで戻りません。この関数は要求された量のデータを読み込もうとします(「短い読み込み」ではありません)。ただし、これはノンブロッキングソケットでは不可能なことがあり、そのような場合は返されるデータが少なくなります。

socket.readinto(buf[, nbytes])

bytes 型オブジェクトを buf に読み込みます。 nbytes が指定されている場合は、最大でそのバイト数だけ読み込みます。 nbytes が指定されない場合は、最大で len(buf) バイトを読み込みます。 read() と同様に、このメソッドは「短い読み込みなし」ポリシーにしたがいます。

戻り値: buf に読み込んで格納されたバイト数。

socket.readline()

改行文字で終わる行を読みます。

戻り値: 読み込んだ行。

socket.write(buf)

ソケットに bytes 型オブジェクトのバッファを書き込みます。この関数は、すべてのデータをソケットに書き込もうとします(「短い書き込み」なし)。ただし、これはノンブロッキングソケットでは不可能なことがあり、そのような場合は戻り値が buf の長さより短くなります。

戻り値: 書き込んだバイト数

exception socket.error

MicroPython にはこの例外がありません。

CPython との違い

CPython には socket.error がありますが廃止予定であり、 OSError の別名となっています。MicroPython では OSError を直接使ってください。