For Development HEAD DRAFTSearch (procedure/syntax/module):

9.22 gauche.net - ネットワーキング

Module: gauche.net

BSDソケットに基づいたネットワーキングに必要な手続きを提供するモジュールです。

2つのレベルのAPIが定義されています。低レベルの手続きはbind(2)のような BSDソケットインタフェースに近いインタフェースを提供し、高レベルの手続きは 典型的なコネクション指向のクライアントサーバアプリケーションに便利な インタフェースを提供します。

また、ホストネームやプロトコルに関する情報にアクセスするAPIも定義されます。

Gaucheは、--enable-ipv6コンフィギュアオプションつきで コンパイルされていれば、IPv6を扱うことができます。 IPv6が使えるかどうかを調べるには、 cond-expand中でgauche.net.ipv6 feature identifierを 使うことができます。次の例を見てください。

(use gauche.net)
(cond-expand
  (gauche.net.ipv6
    ... ipv6を使うコード ...)
  (else
    ... ipv4のみのコード ...))

cond-expandの詳細については機能条件式を 参照してください。

ネットワークを使うポータブルなコードを書きたい場合は、 srfi.106を見てください (srfi.106 - 基本的なソケットインタフェース参照)。


9.22.1 ソケットアドレス

ソケットアドレスオブジェクト

Builtin Class: <sockaddr>

{gauche.net} ソケットアドレスの抽象ベースクラスです。 ソケットアドレスファミリはこのクラスのサブクラスとして実装されます。

ソケットアドレスはビルトインクラスですが、makeメソッドで 特定のソケットアドレスファミリのインスタンスを作成することができます。

Generic Function: sockaddr-family addr

{gauche.net} ソケットアドレスaddrのファミリを表すシンボルを返します。

Generic Function: sockaddr-name addr

{gauche.net} ソケットアドレスaddrの名前を表す文字列を返します。

Builtin Class: <sockaddr-in>

{gauche.net} AF_INETファミリのソケットアドレスです。このクラスのインスタンスを 作成するには、次のようにしてmakeメソッドを呼びます。

(make <sockaddr-in> :host host :port port)

hostは文字列、整数のIPアドレス、u8vectorのIPアドレス、 もしくは:any:broadcast:none:loopbackの いずれかのキーワードでなければなりません。 文字列の場合、それはホスト名かIPアドレスのドット表記です。 Gaucheはgethostbyname(3)を使って実際のIPアドレスを得ます。 この値がキーワード:any:broadcastなら、それぞれ INADDR_ANYINADDR_BROADCASTがアドレスとして使われます。 キーワード:loopbackはIPv4のループバックアドレス"127.0.0.1"を表します。

portはポート番号を示す正の整数です。 2つ以上のプロトコルスタックを持つようなマシン上で複数のソケットアドレスを 生成するには、後述の make-sockaddrs も参照してください。

Method: sockaddr-family (addr <sockaddr-in>)

{gauche.net} シンボルinetを返します。

Method: sockaddr-name (addr <sockaddr-in>)

{gauche.net} 文字列"a.b.c.d:port"を返します。 コロンの前はIPアドレスのドット表記で、portはポート番号です。

Method: sockaddr-addr (addr <sockaddr-in>)
Method: sockaddr-port (addr <sockaddr-in>)

{gauche.net} それぞれ、IPアドレスとポート番号を整数で返します。

Builtin Class: <sockaddr-un>

{gauche.net} AF_UNIXファミリのソケットアドレスです。このクラスのインスタンスを作成するには、 makeメソッドを次のように呼んで下さい。

(make <sockaddr-un> :path path)

pathはソケットのパス名を表す文字列です。

Method: sockaddr-family (addr <sockaddr-un>)

{gauche.net} シンボルunixを返します。

Method: sockaddr-name (addr <sockaddr-un>)

{gauche.net} ソケットアドレスのパス名を返します。

Builtin Class: <sockaddr-in6>

{gauche.net} AF_INET6ファミリのソケットアドレスです。 このクラスはgaucheが–enable-ipv6つきでconfigureされている場合に使えます。 コンストラクタとスロットは<sockaddr-in>と同じです。 2つ以上のプロトコルスタックを持つようなマシン上で複数のソケットアドレスを 生成するには、後述の make-sockaddrs も参照してください。

Function: make-sockaddrs host port :optional proto

{gauche.net} これは上位レベルのユーティリティ手続きで、プロトコル protohost:port を指す、可能なすべてのドメインソケット アドレスを生成します。特に、指定したホストが IPv4 および IPv6 の両方の アドレスを持ち、稼働中のシステムがその両方をサポートしている場合、IPv4 と IPv6 の両方のソケットアドレスが返ります。もし、host が複数の IP アドレスをもつ場合、ソケットアドレスはそれぞれのIPアドレス毎に生成 されます。自分のネットワークアプリケーションを異るネットワークスタックの 設定の間でこれまでよりはるかにポータブルなものにすることができます。

host#f を渡すと、ローカルな(サーバ)アドレスが生成されます。 port 引数に整数のかわりに、サービス名(たとえば、"http")を わたすこともできます。proto の値は、tcp あるいは udp のどちらかのシンボルになります。デフォルトでは、tcp です。

この手続きは常にソケットアドレスのリストを返します。もし、host の 検索に失敗した場合には、空リストが返ります。

アドレスと文字列との変換

Function: inet-string->address address

{gauche.net} 文字列で表現されたインターネットアドレスaddressを整数のアドレス に変換します。addressのパーズが成功した場合には値を2つ返します。 ひとつは整数で表現されたアドレスの値、もうひとつは認識されたプロトコル (定数値で、2 (= AF_INET)ならIPv4アドレス、10 (= AF_INET6)ならIPv6アドレス)です。addressのパーズに失敗した ら、#f#fとの2つが返ります。

(inet-string->address "192.168.1.1")
 ⇒ 3232235777 and 2
(inet-string->address "::1")
 ⇒ 1 and 10
(inet-string->address "::192.168.1.1")
 ⇒ 3232235777 and 10
(inet-string->address "ffe0::1")
 ⇒ 340116213421465348979261631549233168385 and 10
(inet-string->address "::192.168.1.1")
 ⇒ 3232235777 and 10
Function: inet-string->address! address buf

{gauche.net} inet-string->addressと同じですが、整数値を返すかわりに、与えら れたu8vectorであるbufをパーズしたアドレスで埋めるところが違いま す。inetアドレスの整数表現はbignumと同じやりかたです。この関数を使えば bignumを生成しなくてすみます。与えられたu8vectorbufは変更可能で なければなりません。変換に成功した場合はプロトコルが、失敗した場合は #fが返ります。

呼び出し側は格納に十分なバッファを用意しなければなりません。buf が必要な分より大きい場合には結果は先頭から詰められ、ベクタの他の部分は そのままになります。

(let* ((buf (make-u8vector 16 0))
       (proto (inet-string->address! "192.168.1.1" buf)))
  (list proto buf))
 ⇒ (2 #u8(192 168 1 1 0 0 0 0 0 0 0 0 0 0 0 0))
Function: inet-address->string address protocol

{gauche.net} 与えれれたaddressをプロトコルprotocolの文字列表現に変換し ます。プロトコルとしては2 (定数AF_INET)または10 (定数AF_INET6)が指定可能です。addressとしては整数または u8vectorが使えます。u8vectorをつかった場合には必要な部分だけが読み込ま れます。したがって、必要な長さ以上あるベクタでもかまいません。

(inet-address->string 3232235777 AF_INET)
  ⇒ "192.168.1.1"

(inet-address->string '#u8(192 168 1 1) AF_INET)
  ⇒ "192.168.1.1"

(inet-address->string 3232235777 AF_INET6)
  ⇒ "::c0a8:101"

9.22.2 高レベルネットワーク手続き

Builtin Class: <socket>

{gauche.net} 通信の終端であるところのソケットを表すクラスです。

コネクション型のソケットには、入力用と出力用の2つのポートが結び付いており、 それらを使って通信路にアクセスできます。 socket-input-portsocket-output-portはそれぞれ 入力用、出力用のポートを返します。

<socket>クラスはまた、<connection>インタフェースを実装しています (詳しくはgauche.connection - コネクションフレームワーク参照)。 connection-self-addressconnection-peer-addressは ソケットアドレスオブジェクトを返します。

以下の3つは手軽にコネクション型のソケットを作成する ための手続きです。 大抵の場合はこれらの手続きで間に合いますが、 より細かい制御が必要な場合は低レベルAPIを使用して下さい。

Function: make-client-socket :optional address-spec …

{gauche.net} 引数address-spec …によって指定されるアドレスと接続する クライアントソケットを作成して返します。

(make-client-socket 'unix path)

pathで待っているUnixドメインのサーバーソケットに接続します。

(make-client-socket 'inet host port)

ホストhostのポートportにTCPで接続します。 hostはIPv4アドレスのドット表記でもホスト名でも 構いません。Gaucheが–enable-ipv6でコンパイルされていれば、 IPv6形式のアドレス表記も受け付けます。 portはポート番号を指定する正確な整数か、文字列のサービス名 ("http"等)でなければなりません。

Gaucheが–enable-ipv6でコンパイルされており、ホスト名が渡されて、 そのホスト名がIPv6とIPv4の両方のアドレスを持っていた場合は、 最初にIPv6での接続が試みられ、それが失敗した場合にIPv4での接続が試みられます。

(make-client-socket host port)

上と同じです。この形式はSTkとの互換性のために提供されています。

(make-client-socket sockaddr)

<sockaddr>クラスのインスタンスが渡された場合には、それに対応する ソケットをオープンし、そのアドレスへ接続します。

ソケットを作成できなかったり、指定されたアドレスに接続できなかった場合は エラーが報告されます。

(make-client-socket 'inet "www.w3.com" 80)
  ⇒ ;a socket connected to www.w3.com, port 80
(make-client-socket "127.0.0.1" 23)
  ⇒ ;a socket connected to localhost, port 23
(make-client-socket 'unix "/tmp/.sock"
  ⇒ ;a socket connected to a unix domain socket "/tmp/.sock"
Function: make-server-socket :optional address-spec …

{gauche.net} address-specにて接続を待つサーバソケットを作成して返します。

(make-server-socket 'unix path [:backlog num])

パス名pathを持つUnixドメインソケットが作成されます。 キーワード引数backlogに渡された数値はsocket-listenに渡され、 サーバが接続要求を貯めておくキューの最大長を指定します。 デフォルトは5です。多忙なサーバーで、"connection refused"が頻発する場合は この数値を増やしてみて下さい。

(make-server-socket 'inet port [:reuse-addr? flag] [:sock-init proc] [:backlog num])

ポートportにて接続を待つInetドメインのTCPソケットが作成されます。 portは非負の正確な整数か、文字列のサービス名("http"等)でなければなりません。 portが零の場合はシステムが適当なポート番号を割り当てます。 キーワード引数reuse-addr?に真の値が与えられた場合は、 ソケットにSO_REUSEADDRオプションがセットされます。 その場合、他のプロセスが解放したばかりの(TCP)ポートでも エラーとならずに使うことができます。

あるいは、正の正確な整数のリストをportに渡すことも出来ます。 その場合、Gaucheは与えられたポート番号で順にbindを試し、成功したらそのソケットを返します。

キーワード引数sock-initが与えられた場合、proc が出来たての ソケットとそのソケットアドレスを引数にして呼び出されます。 つまり、proc はそのような2つの引数を取る手続きでなければなりません。 ソケットに特殊なオプションを設定したいような場合に便利です。

キーワード引数backlogはunixソケットと同じです。上の記述を参照して下さい。

(make-server-socket port [:reuse-addr? flag] [:sock-init proc][:backlog num])

これは、portが整数でなければならないことを除けば、 上の形式と同じ動作をします。STkのmake-server-socketとの 互換性のために提供されています。

(make-server-socket sockaddr [:reuse-addr? flag][:sock-init proc][:backlog num])

この形式は、listenするソケットアドレスを<sockaddr>のインスタンスで 明示的に指定します。

(make-server-socket 'inet 8080)
  ⇒ #<socket (listen "0.0.0.0:8080")>
(make-server-socket 8080)
  ⇒ #<socket (listen "0.0.0.0:8080")>
(make-server-socket 'inet 0)
  ⇒ #<socket (listen "0.0.0.0:35628")>
(make-server-socket 'unix "/tmp/.sock")
  ⇒ #<socket (listen "/tmp/.sock")>
Function: make-server-sockets host port :key reuse-addr? sock-init

{gauche.net} host が持つすべての利用可能なネットワークインタフェース上の port で接続を待つソケットを生成し、それらのリストを返します。 port には数字のポート番号のほか、"http"などの サービス名も指定できます。

この手続きは、ホストが複数のプロトコルスタック(IPv4とIPv6など)を 持つ場合に特に便利です。その場合、この手続きはIPv4用のソケットと IPv6用のソケットのリストを返すかもしれません。 (OSによっては、一つのソケットでIPv4もIPv6も両方listenできるものが あります。そういったOSでは単一のソケットのリストが返るでしょう。)

キーワード引数の意味はmake-server-socketのと同じです。

make-server-socketと同様、portに0を渡すことで、 システムに空いているポートを自動的にアサインしてもらうことができます。 portに0を渡して複数のソケットが返される場合、それらのソケットは 同じポート番号を持つことが保証されます。

上記の手続きによって返されたソケットオブジェクトに対して、 以下のようなアクセサがあります。

Function: socket-address socket

{gauche.net} ソケットsocketのソケットアドレスを返します。 ソケットにアドレスがまだバインドされていない場合は#fが返ります。

Function: socket-input-port socket :key (buffering :modest)
Function: socket-output-port socket :key (buffering :line)

{gauche.net} それぞれ、socketからデータを読みだす入力ポート、および socketにデータを書き出す出力ポートを返します。

キーワード引数bufferingはポートのバッファリングモードを 指定します。バッファリングモードの説明はファイルポートにあります。

Function: socket-close socket

{gauche.net} ソケットsocketをクローズします。socketの入出力ポートも クローズされます。

注意: リリース 0.7.2 より、この手続きは接続をシャットダウンしないように なりました。その理由は、socket が fork した別プロセスから参照され ている可能性があり、既存の接続を妨害することなくクローズしたい場合がある からです。socket-shutdown を呼べば接続を明示的にシャットダウンできます。

Function: call-with-client-socket socket proc :key input-buffering output-buffering

{gauche.net} socketは接続されたクライアントソケットでなければなりません。 procがソケットから読み出す入力ポートと、 ソケットに書き出す出力ポートを引数として呼ばれます。 procが正常終了するか、エラーを投げた場合にソケットはクローズされます。

キーワード引数input-bufferingoutput-bufferingが与えられた場合、 それらはそれぞれsocket-input-portsocket-output-portbufferingキーワード引数へと渡されます。

これは高レベルソケット手続きを使った、非常に単純なhttpクライアントです。

#!/usr/bin/env gosh
(use gauche.net)

(define (usage)
  (display "Usage: swget url\n" (current-error-port))
  (exit 1))

;; Returns three values: host, port, and path.
(define (parse-url url)
  (rxmatch-let (rxmatch #/^http:\/\/([-A-Za-z\d.]+)(:(\d+))?(\/.*)?/ url)
      (#f host #f port path)
    (values host port path)))

(define (get url)
  (receive (host port path) (parse-url url)
    (call-with-client-socket
        (make-client-socket 'inet host (string->number (or port "80")))
      (lambda (in out)
        (format out "GET ~a HTTP/1.0\r\n" path)
        (format out "host: ~a\r\n\r\n" host)
        (flush out)
        (copy-port in (current-output-port))))))

(define (main args)
  (if (= (length args) 2)
      (get (cadr args))
      (usage))
  0)

9.22.3 低レベルソケットインタフェース

ここにある関数群はシステムコールと類似した API を提供します。 ソケット API プログラミングに慣れていれば、ソケットをより細かく 制御できるので、役に立つでしょう。

Function: make-socket domain type :optional protocol

{gauche.net} パラメータで指定したソケットを返します。

Constant: PF_UNIX
Constant: PF_INET
Constant: PF_INET6

{gauche.net} これらの定数はそれぞれシステムが提供するPF_UNIXPF_INETPF_INET6に束縛されています。 これらの値をmake-socketdomain引数に使うことができます。

(PF_INET6はオペレーティングシステムがIPv6をサポートしている場合にのみ 定義されます。)

Constant: AF_UNIX
Constant: AF_INET
Constant: AF_INET6

{gauche.net} これらの定数はそれぞれ、AF_UNIXAF_INETAF_INET6 に束縛されています。

(AF_INET6はオペレーティングシステムがIPv6をサポートしている場合にのみ 定義されます。)

Constant: SOCK_STREAM
Constant: SOCK_DGRAM
Constant: SOCK_RAW

{gauche.net} これらの定数はそれぞれ、SOCK_STREAMSOCK_DGRAMSOCK_RAW に束縛されており、 make-sockettype引数に使うことができます。

Function: socket-fd socket

{gauche.net} ソケットのもつ整数のシステムファイルディスクリプタを返します。

Function: socket-status socket

{gauche.net} socket の内部状態を、以下のシンボルのどれかで返します。

none生成直後
boundsocket-bind によって、あるアドレスに束縛されている
listeningsocket-listen によって、接続をリッスンしている
connectedsocket-connect あるいは socket-accept によって接続されている
shutdownsocket-shutdown によってシャットダウンされた
closedsocket-close によってクローズされた
Function: socket-bind socket address

{gauche.net} socket をローカルネットワークアドレス address に束縛します。 通常は、特定のアドレスをこのサーバのポートに結びつけるのに用います。 もし、束縛が失敗したら(多くの場合、そのアドレスが既に使用されている)、 エラーシグナルが発生します。

INET ドメインアドレスの場合には port=0 とした address を 渡せます。システムがポート番号を割当て、socketaddress スロットに実際のアドレスをセットします。

Function: socket-listen socket backlog

{gauche.net} socket をリッスンします。ソケットは既になんらかのアドレスに 束縛されていなければなりません。backlog はキューに入れる 接続要求の最大数を指定します。

Function: socket-accept socket

{gauche.net} socketに来た接続要求をアクセプトします。リモートエンティティへ 接続している新しいソケットを返します。元の socket は引き続き 次の接続要求を待ちます。接続要求がないとき、これの呼出しは要求が 一つ来るまで待ちます。

接続要求をペンディングしているかどうかをチェックするのに sys-selectが使えます。

Function: socket-connect socket address

{gauche.net} socket をリモートアドレス address に接続します。 これは、クライアントソケットをリモートエンティティに接続するための 方法です。

Function: socket-shutdown socket how

{gauche.net} socket の接続をシャットダウンします。howSHUT_RD (0) なら、 socket の受信チャネルが不許可となります。howSHUT_WR (1)なら、 socket の送信チャネルが不許可となります。howSHUT_RDWR (2)なら、 socket の送受信チャネルの両方が不許可となります。 接続していないソケットに対して、この手続きを呼ぶとエラーになります。

ソケットの送信チャネルをシャットダウンすると、リモート側の受信チャネル に EOF があらわれます。これは、リモート側が何かを送り返す前に EOF を受けとることを期待している場合、便利です。

Function: socket-getsockname socket

{gauche.net} socketのローカル側アドレスを表す<sockaddr>インスタンスを返します。

Function: socket-getpeername socket

{gauche.net} socketの通信相手のアドレスを表す<sockaddr>インスタンスを返します。

Function: socket-send socket msg :optional flags
Function: socket-sendto socket msg to-address :optional flags.

{gauche.net} それぞれ、send(2) および sendto(2) へのインタフェース。 msg の内容を socket を通じて送出します。 msgは文字列もしくはユニフォームベクタでなければなりません。 バイナリパケットを送る場合はユニフォームベクタの使用を推奨します。

実際に送出されたオクテット数を返します。

socket-send を使うときには、socket は既に接続されて いなければなりません。他方、socket-sendto は未接続の ソケットに対して使用でき、送出先アドレスは <sockaddr> のインスタンス to-address で指定します。

オプション引数 flags は整数定数 MSG_* のビット毎のORで 指定できます。詳しくはシステムの man ページ send(2) および sendto(2) を見て下さい。

Function: socket-sendmsg socket msghdr :optional flags

{gauche.net} sendmsg(3)を使って、msghdrで記述されるパケットをsocket を通じて送ります。msghdr引数は文字列かu8vectorで、 struct msghdr構造体のバイナリ表現でなければなりません。 msghdr引数に適したデータを構築する確かな方法は、下に述べる socket-buildmsgを使うことです。

flags引数はsocket-sendおよびsocket-sendtoと同じです。

送り出されたオクテット数を返します。

この手続きはWindowsネイティブ環境では(まだ)サポートされません。 これが使えるかどうかは、機能識別子gauche.os.windowsを使って判定 できます (プラットフォーム依存の機能参照)。

Function: socket-buildmsg addr iov control flags :optional buf

{gauche.net} struct msghdr構造体のバイナリ表現を構築します。 作られたmsghdrはsocket-sendmsgに渡すことができます。 この手続きを理解するには、sendmsg(3)の動作をよく知っていることが必要です。

addr引数は<sockaddr>のインスタンスか#fでなければ なりません。<sockaddr>のインスタンスである場合、そのアドレスが msghdrのmsg_nameフィールドに使われます。

iov引数はベクタか#fでなければなりません。ベクタの場合、 各要素は文字列かu8vectorでなければなりません。これはmsghdrの msg_iovフィールドに使われます。各要素の内容はカーネル内で 結合されてペイロードとなります。

control引数は補助データ(cmsg)を指定します。補助データが必要ない 場合は#fを渡せます。そうでなければ、control引数は 次の形式を持つリストでなければなりません。

((level type data) ...)

leveltypeは正確な整数で、dataは文字列かu8vectorの いずれかです。 最初の2つはそれぞれcmsgのcmsg_levelcmsg_typeフィールドを指定します。dataはcmsgのデータとなります。 (cmsg_lendataから計算されます)。

flags引数はmsg_flagsフィールドに使われます。

buf引数が省略されるか#fの場合、msghdrを構築するのに 必要なメモリがアロケートされます。書き換え可能なu8vectorがbuf に渡されれば、socket-buildmsgはできるだけそれをバッファに使って msghdrを構築しようとします。bufで領域が不足する場合のみ 新たなメモリをアロケートします。

この手続きは構築されたmsghdrをu8vectorとして返します。

この手続きはWindowsネイティブ環境では(まだ)サポートされません。 これが使えるかどうかは、機能識別子gauche.os.windowsを使って判定 できます (プラットフォーム依存の機能参照)。

Function: socket-recv! socket buf :optional flags

{gauche.net} recv(2)へのインタフェースです。socketからメッセージを 受信し、それを変更可能なユニフォームベクタbufへと書き込みます。 そして実際に書き込まれたバイト数を返します。 socketは既にコネクトされていなければなりません。 bufの大きさが受信したメッセージより小さい場合、socketの タイプによっては残りのメッセージは捨てられる可能性があります。

オプション引数 flags は整数定数 MSG_* のビット毎のORで 指定できます。詳しくはシステムの man ページ recv(2)を見て下さい。

Function: socket-recvfrom! socket buf addrs :optional flags

{gauche.net} recvfrom(2)へのインタフェースです。socketからメッセージを 受け取り、変更可能なユニフォームベクタへ書き込みます。socketは コネクトされていなくても構いません。socket-recvと同様に、 bufの大きさがメッセージ全てを保持するのに十分でない場合、 socketのタイプによっては残りのメッセージは捨てられます。

ふたつの値を返します。実際にbufに書かれたバイト数と、 送信者のアドレスを示す<sys-sockaddr>のサブクラスのインスタンスです。

addrs引数はソケットアドレスインスタンスのリストでなければなりません。 ただし、リストの終端 (最後のcdr) は#tであっても許されます。 (この特殊な場合として、addrs引数にただ#tを渡すことも許されます)。 addrs引数に渡されたソケットアドレスの中身は何でも構いません。 送信者のアドレスファミリーに一致するソケットアドレスインスタンスがaddrs 中にあった場合、socket-recvfrom!はそのインスタンスに直接 送信者のアドレスを書き込みます。受信し得る全てのアドレスファミリのソケットアドレスを リストで渡しておけば、socket-recvfrom!が(成功時には) メモリアロケーションを行わないことが保証されます。これは 速度が重要となるタイトなループ内でsocket-recvfrom!を呼ぶ場合に 重要です。

送信者のアドレスファミリに一致するソケットアドレスがあたえられなかった場合、 socket-recvfrom!の振舞いはaddrsのリスト終端の値によります。 addrs()で終端されていた場合 (addrsが真性リストで あった場合)、送信者のアドレスは捨てられ、socket-recvfrom!は 二番めの値として#fを返します。addrs#tで終端 されていた場合、socket-recvfrom!は新たなソケットアドレス インスタンスを作成して返します。

簡単な場合として次の二つがあります:addrs()が渡された場合、 送信者のアドレスは常に捨てられます。socketがコネクトされていれば 送信者のアドレスは既にわかっているので、そういう場合に便利でしょう。 一方addrs#tを渡せば、常に新しいソケットアドレスが アロケートされて返されます。メモリアロケーションについて気にしなくても 良い場合は便利でしょう。

オプション引数 flags は整数定数 MSG_* のビット毎のORで 指定できます。詳しくはシステムの man ページ recvfrom(2)を見て下さい。

Function: socket-recv socket bytes :optional flags
Function: socket-recvfrom socket bytes :optional flags

{gauche.net} socket-recv!socket-recvfrom!と似ていますが、 受け取ったメッセージを(不完全かもしれない)文字列として返します。 bytesは受信する上限のバイト数を指定します。 socket-recvfromはそれに加えて、送信者のアドレスのために 常に新たなソケットアドレスオブジェクトを生成します。

これらの手続きの使用はお薦めしません。というのは、バイナリメッセージを 不完全な文字列の形で扱うことになりがちだからです。文字列で バイナリメッセージを取り扱うことは多くの落とし穴を作ります。 バイナリデータを扱う場合はユニフォームベクタ (特にu8vector) を使うべきでしょう。 (これらの手続きが文字列を返すのは単に歴史的な理由によります)。

Variable: MSG_CTRUNC
Variable: MSG_DONTROUTE
Variable: MSG_EOR
Variable: MSG_OOB
Variable: MSG_PEEK
Variable: MSG_TRUNC
Variable: MSG_WAITALL

{gauche.net} socket-sendsocket-sendtosocket-recv および socket-recvfromflag として使う定義済み整数定数。 これらの定数のいくつかは、基盤のOSが提供していなければ未定義に なっています。

以下に解説する getsockopt/setsockopt インタフェースを使えば、 ソケットやプロトコルをさらに制御することができます。

Function: socket-setsockopt socket level option value
Function: socket-getsockopt socket level option rsize

{gauche.net} これらは、setsockopt() および getsockopt() を呼ぶための インタフェースです。このインタフェースが少々ぎこちないのは、 低レベルの呼び出しすべてにアクセスできるようにしているためです。

socket および option は、処理する対象の プロトコルスタックのレベルおよびオプションを指定する 正確な整数です。以下にリストアップしたシステム定数に束縛された 変数があります。

ソケットオプションを設定するには、value に正確な整数を渡す方法と 文字列を渡す方法があります。それが、整数なら、その値は、C の int として setsockopt (2) に渡されます。文字列なら、バイト列が そのまま渡されます。どの型の値が要求されるかは、オプションに依存します。 Gauche 側では渡された値が setsockopt (2) で期待された型であるかどうかは 知ることができません。正しい値が渡されるかどうかはプログラマの責任です。

ソケットオプションを知るには、結果として期待する最大の長さを rsize を使って教える必要があります。Gauche 側は返されるそれぞれのオプションの 合計を知らないからです。 socket-getsockopt はオプションの値をバイト列として返します。 オプションの値が整数だと、わかっているなら rsize に0を渡すこと ができます。その場合 socket-getsockopt は正確な整数として値を返します。

関数名に関する註: これらの関数の名前を socket-{set|get}opt あるいは socket-{set|get}-option にしようかとも思いましたが、結局、命名の 一貫性をとることにしました。それで、"sock" が重複しています。

以下のような定義済みの変数が用意されています。 すべてのプラットフォームで利用できるわけではないものも含まれている ことに注意してください。 これらの値の正確な使用は、お使いのシステムの man ページ socket(7)tcp(7) あるいは ip(7) を参照してください。

“level” 引数

Variable: SOL_SOCKET
Variable: SOL_TCP
Variable: SOL_IP

{gauche.net} これらの変数は、それぞれ、SOL_SOCKETSOL_TCP および SOL_IP に束縛されています。

“option” 引数

Variable: SO_KEEPALIVE

{gauche.net} 整数が期待されています。0でなければ、コネクション指向ソケットに キープアライブ(keep-alive)メッセージを送ることができます。

Variable: SO_OOBINLINE

{gauche.net} 整数が期待されています。0でなければ、帯域外データは直接 受信データストリームに乗ります。さもなければ、帯域外データは、受信中に MSG_OOBフラグが設定されてたときにのみ渡されます。

Variable: SO_REUSEADDR

{gauche.net} 整数が期待されています。0ではない場合、socket-bindは、 ローカル・アドレスが、アクティブソケットにリッスンされていない 場合にかぎり、そのアドレスを再利用することを許可されます。

Variable: SO_TYPE

{gauche.net} ソケットの型(sock_streamなど)を整数として取得します。 socket-getsockoptでのみ使用可能です。

Variable: SO_BROADCAST

{gauche.net} 整数が期待されています。0でなければ、データグラムソケットは ブロードキャストパケットを送受信することを許されます。

Variable: SO_PRIORITY

{gauche.net} 整数が期待されています。このソケットで送信されるすべてのパケットに ついてプロトコル定義の優先順位を指定します。

Variable: SO_ERROR

{gauche.net} 保留状態のソケットエラー(整数値)を取得し、それをクリアします。 socket-getsockoptでのみ使用可能です。

Function: inet-checksum packet size

{gauche.net} ユニフォームベクタで与えられるpacketのインターネットチェックサム(RFC1071) の1の補数を計算して返します。packetの最初のsizeバイトのみが 計算の対象となります。返される値はネットワークバイトオーダ (ビッグエンディアン) です。packetより大きな値をsizeに指定するとエラーとなります。

註: 使われているアルゴリズムは、packetがそれほど大きくないこと (< 64K) を 仮定しています。


9.22.4 Netdbインタフェース

Builtin Class: <sys-hostent>

{gauche.net} このクラスはネットワークホストのオブジェクト用で、 C の struct hostent に対応しています。以下のスロットは読み込み専用です。

Instance Variable of <sys-hostent>: name

ホストの正式名(文字列)

Instance Variable of <sys-hostent>: aliases

ホストの別名リスト(文字列のリスト)

Instance Variable of <sys-hostent>: addresses

アドレスのリスト(文字列のリスト)。現時点では IPv4 のアドレスのみサポート しています。それぞれのアドレスは、ドットつき十進記法で表記されています。

Function: sys-gethostbyname name

{gauche.net} nameという名前のホストを探し、見つかれば、<sys-hostent> オブジェクトを返します。見つからなければ、#f を返します。

(let ((host (sys-gethostbyname "www.w3c.org")))
  (list (slot-ref host 'name)
        (slot-ref host 'aliases)
        (slot-ref host 'addresses)))
  ⇒ ("www.w3.org" ("www.w3c.org") ("18.29.1.34" "18.29.1.35"))
Function: sys-gethostbyaddr addr proto

{gauche.net} protoというプロトコルの、addrというアドレスを持つホストを 探します。addrはアドレスの自然な文字列表現で、IPv4 については、 ドットつき十進記法です。protoはプロトコル番号で、現時点では AF_INETのみサポートされています。ホストが見つかれば、 <sys-hostent>オブジェクトを返します。 見つからなければ、#f を返します。

(let ((host (sys-gethostbyaddr "127.0.0.1" AF_INET)))
  (list (slot-ref host 'name)
        (slot-ref host 'aliases)
        (slot-ref host 'addresses))
  ⇒ ("localhost" ("localhost.localdomain") ("127.0.0.1"))
Builtin Class: <sys-servent>

{gauche.net} ネットワークサービスデータベースのエントリです。 C の struct serventに対応しています。 以下のスロットは読み込み専用です。

Instance Variable of <sys-servent>: name

サービスの正式名(文字列)

Instance Variable of <sys-servent>: aliases

サービスの別名リスト(文字列のリスト)

Instance Variable of <sys-servent>: port

サービスに割り当てられたポート番号(正確な整数)

Instance Variable of <sys-servent>: proto

このサービス用のプロトコル名(文字列)

Function: sys-getservbyname name proto

{gauche.net} ネットワークサービスデータベースをサービス名 name および プロトコル proto で検索します。name および proto は文字列でなければなりません。サービスが見つかれば、<sys-servent> のインスタンスを返します。見つからなければ、#f を返します。

(let ((serv (sys-getservbyname "http" "tcp")))
  (list (slot-ref serv 'name)
        (slot-ref serv 'aliases)
        (slot-ref serv 'port)
        (slot-ref serv 'proto)))
  ⇒ ("http" () 80 "tcp")
Function: sys-getservbyport port proto

{gauche.net} ネットワークサービスデータベースをサービス名 port および プロトコル proto で検索します。port は正確な整数でなければ なりません。また、proto は文字列でなければなりません。 サービスが見つかれば、<sys-servent> のインスタンスを返します。見つからなければ、#f を返します。

(let ((serv (sys-getservbyport 6000 "tcp")))
  (list (slot-ref serv 'name)
        (slot-ref serv 'aliases)
        (slot-ref serv 'port)
        (slot-ref serv 'proto)))
  ⇒ ("x-server" () 6000 "tcp")
Builtin Class: <sys-protoent>

{gauche.net} プロトコルデータベースのエントリです。C の struct protoentに 対応しています。以下のスロットは読み込み専用です。

Instance Variable of <sys-servent>: name

プロトコルの正式名(文字列)

Instance Variable of <sys-servent>: aliases

プロトコルの別名のリスト(文字列のリスト)

Instance Variable of <sys-servent>: proto

プロトコル番号(正確な整数)

Function: sys-getprotobyname name

{gauche.net} 名前 name でネットワークプロトコルデータベースを検索します。 名前 name は文字列でなければなりません。 プロトコルが見つかれば、<sys-protoent> のインスタンスを返します。見つからなければ、#f を返します。

(let ((proto (sys-getprotobyname "icmp")))
  (list (slot-ref proto 'name)
        (slot-ref proto 'aliases)
        (slot-ref proto 'proto)))
  ⇒ ("icmp" ("ICMP") 1)
Function: sys-getprotobynumber number

{gauche.net} プロトコル番号 number でネットワークプロトコルデータベースを検索 する。プロトコル番号 number は正確な整数でなければなりません。 プロトコルが見つかれば、<sys-protoent> のインスタンスを返します。見つからなければ、#f を返します。

(let ((proto (sys-getprotobynumber 17)))
  (list (slot-ref proto 'name)
        (slot-ref proto 'aliases)
        (slot-ref proto 'proto)))
  ⇒ ("udp" ("UDP") 17)
Builtin Class: <sys-addrinfo>

{gauche.net} アドレス情報を保持する新しいインタフェースです。C の struct addrinfo に対応しています。これは gauche が –enable-ipv6 オプションで設定され、 ビルドされた場合にのみ利用可能です。以下のスロットが提供されます。

Instance Variable of <sys-addrinfo>: flags
Instance Variable of <sys-addrinfo>: family
Instance Variable of <sys-addrinfo>: socktype
Instance Variable of <sys-addrinfo>: protocol
Instance Variable of <sys-addrinfo>: addrlen
Instance Variable of <sys-addrinfo>: addr
Function: sys-getaddrinfo nodename servname hints

{gauche.net} 与えられた nodenameservname および hints から <sys-addrinfo> のインスタンスのリストを返します。 これは gauche が –enable-ipv6 オプションで設定され、 ビルドされた場合にのみ利用可能です。

Function: sys-ntohs integer
Function: sys-ntohl integer
Function: sys-htons integer
Function: sys-htonl integer

{gauche.net} 16bit (s)もしくは32bit (l) の整数を ネットワークバイト順 (n) とホストバイト順 (h) の間で 相互変換するユーティリティ関数です。

netdbインタフェースのScheme APIは必要な箇所ではこれらの関数を内部的に 呼んでいるので、Cでプログラミングしている時ほどこれらの関数を必要とする ことはないでしょう。ただ、バイナリデータパケットを構築したり解析したり する際は便利かもしれません。バイナリデータの扱いについては binary.pack - バイナリデータのパックも参照して下さい。



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT