6.93. kink/socket/TCP

ストリームベースのコネクティングソケットを提供する。

次のプログラムは、TCP/IPのサーバとクライアントを立ち上げる。クライアントはTCP_NODELAY, SO_SNDBUF, SO_LINGERのソケットオプションを設定し、バイト列 [1, 2, 3] をサーバに送る。

:TCP.require_from('kink/socket/')
:TCP_SERVER.require_from('kink/socket/')
:IP.require_from('kink/socket/')
:IP_PORT.require_from('kink/socket/')
:THREAD.require_from('kink/thread/')
:BIN.require_from('kink/')
:CONTROL.require_from('kink/')

:spawn_client <- {(:Server_addr)
  THREAD.spawn_io{
    CONTROL.with_finally{(:finally)
      :Tcp = TCP.open
      finally{ Tcp.close }

      # initial socket options
      stdout.print_line(Tcp.tcp_nodelay.load.repr) # => false
      stdout.print_line(Tcp.so_sndbuf.load.repr) # => 8192 (initial values vary for systems)
      stdout.print_line(Tcp.so_linger.load.repr) # => []

      # set socket options
      Tcp.tcp_nodelay <- true
      Tcp.so_sndbuf <- 1024
      Tcp.so_linger <- [10]
      stdout.print_line(Tcp.tcp_nodelay.load.repr) # => true
      stdout.print_line(Tcp.so_sndbuf.load.repr) # => 2304 (the value was adjusted)
      stdout.print_line(Tcp.so_linger.load.repr) # => [10]

      Tcp.connect(Server_addr)
      :Out = Tcp.output
      finally{ Out.close }

      Out.write(BIN.of(1))
      Out.write(BIN.of(2))
      Out.write(BIN.of(3))
    }
  }
}

CONTROL.with_finally{(:finally)
  :Server = TCP_SERVER.open
  finally{ Server.close }

  Server.bind_listen(IP_PORT.new(IP.for_hostname('::1') 0))
  :Server_addr = Server.local_address
  spawn_client(Server_addr)

  :Tcp = Server.accept
  finally{ Tcp.close }
  :In = Tcp.input
  finally{ In.close }

  :Bin = In.read_all
  stdout.print_line(Bin.repr) # => (bin 0x01 0x02 0x03)
}

6.93.1. tcp型

tcpはストリームベースのコネクティングソケットである。プロトコルは、TCP/IPか、ストリームベースのUnixドメインソケットのどちらかである。

6.93.1.1. Tcp.connect(Remote ...[$config={}])

connectはソケットを、Remoteで指定されたリモートアドレスに接続する。

コンフィグメソッド:

• C.on_success($success): default = {}

• C.on_error($error): default = {(:Exc) Exc.raise }

• C.on_closed($closed): default = $errorを末尾呼び出しするサンク

connectは、接続が確立するか、ソケットが閉じられるか、IOエラーが発生するまで待つ。

接続が確立した場合、connectは$successを引数なしで末尾呼び出しする。クライアントはソケットからデータを読んだり、ソケットにデータを書いたりできる。

connectの呼び出しの前、または呼び出し中に、コネクティングソケットが閉じられた場合、connectは$closedを引数なしで末尾呼び出しする。

IOエラーが起きた場合、connectはコネクティングソケットを閉じて、exceptionを引数として$errorを末尾呼び出しする。

タイムアウト

接続タイムアウトは、C.on_closedとTcp.close_unless_connectedで実装できる。

:TCP.require_from('kink/socket/')
:IP.require_from('kink/socket/')
:IP_PORT.require_from('kink/socket/')
:THREAD.require_from('kink/thread/')
:CONTROL.require_from('kink/')
:PROCESS.require_from('kink/')

CONTROL.with_finally{(:finally)
  :Tcp = TCP.open
  finally{ Tcp.close }

  # a blackhole address. see RFC 6666
  :Blackhole = IP_PORT.new(IP.for_hostname('0100::1234') 8080)

  # times out connection after 10 seconds
  THREAD.spawn_io{
    THREAD.sleep(10)
    Tcp.close_unless_connected
  }

  # exits the process when connection times out
  Tcp.connect(Blackhole){(:C)
    C.on_closed{
      stderr.print_line('connection time out')
      PROCESS.exit(76)
    }
  }
}
# => connection time out

ランタイムやオペレーティングシステムも、それぞれ接続のタイムアウトを行うかもしれない。この場合、$closedが末尾呼び出しされる代わりに、IOエラーが起きるかもしれない。

事前条件

Remoteはsocket_addressであり、ソケットのプロトコルファミリと合致しなければならない。

$successはサンクでなければならない。

$errorはexceptionを引数に取る関数でなければならない。

$closedはサンクでなければならない。

6.93.1.2. Tcp.bind(Local ...[$config])

bindは、Localで指定されたローカルアドレスをソケットに束縛する。

コンフィグメソッド:

• C.on_success($success): default = {}

• C.on_error($error): default = {(:Exc) Exc.raise }

アドレスが成功裏に束縛された場合、bindは引数なしで$successを末尾呼び出しする。

IOエラーが起きた場合、bindはexceptionを渡して$errorを末尾呼び出しする。

事前条件

Localはsocket_addressであり、ソケットのプロトコルファミリと合致しなければならない。

$successはサンクでなければならない。

$errorはexceptionを引数に取る関数でなければならない。

6.93.1.3. Tcp.close(...[$config={}])

closeはコネクティングソケットを閉じる。

コンフィグメソッド:

• C.on_success($success): default = {}

• C.on_error($error): default = {(:Exc) Exc.raise }

ソケットが成功裏に閉じられた場合、closeは$successを引数なしで末尾呼び出しする。

IOエラーが起きた場合、closeは、exceptionを引数として$errorを末尾呼び出しする。

事前条件

$successはサンクでなければならない。

$errorはexceptionを引数に取る関数でなければならない。

6.93.1.4. Tcp.close_unless_connected(...[$config={}])

close_unless_connectedは、ソケットが接続されていない場合に限って、コネクティングソケットを閉じる。ソケットが接続されている場合、またはすでに閉じられている場合、close_unless_connectedは何もしない。

コンフィグメソッド:

• C.on_success($success): default = {}

• C.on_error($error): default = {(:Exc) Exc.raise }

ソケットが接続されている場合、またはすでに閉じられている場合、close_unless_connectedは引数なしで$successを末尾呼び出しする。

ソケットが接続されていない場合、close_unless_connectedはソケットを閉じる。成功した場合、close_unless_connectedは引数なしで$successを末尾呼び出しする。IOエラーが起きた場合、close_unless_connectedは、exceptionを引数として$errorを末尾呼び出しする。

事前条件

$successはサンクでなければならない。

$errorはexceptionを引数に取る関数でなければならない。

6.93.1.5. Tcp.input(...[$config={}])

inputメソッドはコネクティングソケットからinputを作る。

コンフィグメソッド:

• C.buffer(...[Max_buf_size])

C.bufferが呼ばれた場合、結果のinputはユーザ空間でのバッファリングを行う。Max_buf_sizeが渡された場合、バッファサイズはMax_buf_sizeを超えない。C.bufferが呼ばれなければ、inputはユーザ空間でのバッファリングを行わない。

inputを閉じると、ソケットの入力ストリームが遮断される。

事前条件

Max_buf_sizeは正の整数のnum値でなければならない。

6.93.1.6. Tcp.output(...[$config={}])

outputメソッドはコネクティングソケットからoutputを作る。

コンフィグメソッド:

• C.buffer(...[Max_buf_size])

C.bufferが呼ばれた場合、結果のoutputはユーザ空間でのバッファリングを行う。Max_buf_sizeが渡された場合、バッファサイズはMax_buf_sizeを超えない。C.bufferが呼ばれなければ、outputはユーザ空間でのバッファリングを行わない。

outputを閉じると、ソケットの出力ストリームが遮断される。

事前条件

Max_buf_sizeは正の整数のnum値でなければならない。

6.93.1.7. Tcp.local_address(...[$config={}])

local_addressは、コネクティングソケットのローカルアドレスのsocket_addressを取得する。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity

• C.on_error($error): default = {(:Exc) Exc.raise }

ローカルアドレスがある場合、local_addressは、socket_addressを引数として$successを末尾呼び出しする。

IOエラーが起きた場合、local_addressは、exceptionを引数として$errorを末尾呼び出しする。

事前条件

$successは、socket_addressを引数に取る関数でなければならない。

$errorはexceptionを引数に取る関数でなければならない。

6.93.1.8. Tcp.remote_address(...[$config={}])

remote_addressは、コネクティングソケットのリモートアドレスのsocket_addressを取得する。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity

• C.on_error($error): default = {(:Exc) Exc.raise }

リモートアドレスがある場合、remote_addressは、socket_addressを引数として$successを末尾呼び出しする。

IOエラーが起きた場合、remote_addressは、exceptionを引数として$errorを末尾呼び出しする。

事前条件

$successは、socket_addressを引数に取る関数でなければならない。

$errorはexceptionを引数に取る関数でなければならない。

6.93.1.9. Tcp.tcp_nodelay

tcp_nodelayは、TCP_NODELAYオプションのbool値のrefを戻す。

ソケットオプションの使い方については、このモジュールの先頭の例示のプログラムを見よう。

事前条件

プロトコルファミリはipv4かipv6でなければならない。

6.93.1.10. Tcp.so_keepalive

so_keepaliveは、SO_KEEPALIVEオプションのbool値のrefを戻す。

ソケットオプションの使い方については、このモジュールの先頭の例示のプログラムを見よう。

事前条件

プロトコルファミリはipv4かipv6でなければならない。

6.93.1.11. Tcp.so_reuseaddr

so_reuseaddrは、SO_REUSEADDRオプションのbool値のrefを戻す。

ソケットオプションの使い方については、このモジュールの先頭の例示のプログラムを見よう。

事前条件

プロトコルファミリはipv4かipv6でなければならない。

6.93.1.12. Tcp.so_linger

so_lingerは、SO_LINGERオプションを表す、オプショナルな非負な整数のnum値のrefを戻す。

refの値は、空のvecか、 一要素のvec [l_linger] のいずれかである。ここでl_lingerは、非負の整数のnumである。値が空のvecのとき、SO_LINGERオプションは無効にされる。値が一要素のvecのとき、SO_LINGERは有効になり、l_lingerがタイムアウト秒数になる。

ソケットオプションの使い方については、このモジュールの先頭の例示のプログラムを見よう。

事前条件

プロトコルファミリはipv4かipv6でなければならない。

6.93.1.13. Tcp.so_sndbuf

so_sndbufは、SO_SNDBUFオプションの、非負な整数のnum値のrefを戻す。

ソケットオプションの使い方については、このモジュールの先頭の例示のプログラムを見よう。

6.93.1.14. Tcp.so_rcvbuf

so_rcvbufは、SO_RCVBUFオプションの、非負な整数のnum値のrefを戻す。

ソケットオプションの使い方については、このモジュールの先頭の例示のプログラムを見よう。

6.93.2. TCP.open(...[Protocol_family=PROTOCOL_FAMILY.ipv6 $config={}])

openは、新しいコネクティングソケットを作る。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity

• C.on_error($error): default = {(:Exc) Exc.raise }

• C.on_unsupported($unsupported): default = $erroを末尾呼び出しする関数

ソケットが作られた場合、openは、tcpを引数として$successを末尾呼び出しする。

指定されたプロトコルファミリをランタイムがサポートしない場合、openは引数なしで$unsupportedを末尾呼び出しする。

IOエラーが起きた場合、openは、exceptionを引数として$errorを末尾呼び出しする。

事前条件

Protocol_familyはprotocol_familyでなければならない。

$successは、tcpを取る関数でなければならない。

$errorはexceptionを引数に取る関数でなければならない。

$unsupportedはサンクでなければならない。

6.93.3. TCP.is?(Val)

is?は、Valがtcp値であるかどうかを戻す。