6.94. kink/socket/TCP_SERVER¶
Provides listening sockets of TCP/IP, or stream based Unix Domain Socket.
Example
The following program spawns a TCP/IP server and a client. The server sets socket options SO_REUSEADDR and SO_RCVBUF. The client sends bytes [1, 2, 3] to the server.
: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 }
Tcp.connect(Server_addr)
:Out = Tcp.output
finally{ Out.close }
Out.write(BIN.of(1 2 3))
}
}
}
CONTROL.with_finally{(:finally)
:Server = TCP_SERVER.open
finally{ Server.close }
Server.so_reuseaddr <- true
Server.so_rcvbuf <- 1024
stdout.print_line(Server.so_reuseaddr.load.repr) # => true
stdout.print_line(Server.so_rcvbuf.load.repr) # => 1152
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.94.1. type tcp_server¶
A `tcp_server` is a listening socket of TCP/IP, or stream based Unix Domain Socket.
6.94.1.1. Serv.bind_listen(Local ...[$config_fun={}])¶
`bind_listen` binds the local address to the listening socket, and changes the socket to listening mode.
Config methods:
• C.backlog(Backlog): default = the runtime default
• C.on_success($success): default = {}
• C.on_error($error): default = {(:Exc) Exc.raise }
If the socket is changed to listening mode, `bind_listen` tail-calls $success with no arg.
If an IO error occurs, `bind_listen` tail-calls $error with an `exception`.
`Backlog` is used as a preferred maximum number of connections which are established but not accepted.
Preconditions
`Local` must be a `socket_address` whose protocol family is acceptable by the socket.
`Backlog` must be a positive integer `num`.
$success must be a thunk.
$error must be a function which takes an `exception`.
6.94.1.2. Serv.accept(...[$config={}])¶
`accept` method accepts an incoming connection.
Config methods:
• C.on_success($success): default = VAL.identity
• C.on_error($error): default = {(:Exc) Exc.raise }
• C.on_cancelled($cancelled): default = a function which raises an exception
`accept` method waits until a connection becomes established, an IO error occurs, or it is cancelled.
If a connection is established, `accept` tail-calls $success with a `tcp` value of the connecting socket.
If an IO error occurs, `accept` tail-calls $error with an `exception`.
If `accept` is cancelled, `accept` tail-calls $cancelled with no arg.
Precondition
The socket must be in listening mode.
$success must be a function which takes a `tcp`.
$error must be a function which takes an `exception`.
$cancelled must be a thunk.
6.94.1.3. Serv.cancel_accept¶
`cancel_accept` cancels the current or the next `accept` operation of this listening socket.
If no other thread is blocked in `accept` operation, the next invocation of `accept` will be cancelled.
If a single thread is blocked in `accept` operation, the invocation of `accept` will be cancelled.
If multiple threads are blocked in `accept` operation, one of them will be cancelled.
6.94.1.4. Serv.close(...[$config={}])¶
`close` closes the listening socket.
Config methods:
• C.on_success($success): default = {}
• C.on_error($error): default = {(:Exc) Exc.raise }
If the socket is closed successfully, `close` tail-calls $success with no arg.
If an IO error occurs, `close` tail-calls $error with an `exception`.
Preconditions
$success must be a thunk.
$error must be a function which takes an `exception`.
6.94.1.5. Serv.local_address(...[$config={}])¶
`local_address` retrieves the `socket_address` of the local address of the listening socket.
Config methods:
• C.on_success($success): default = VAL.identity
• C.on_error($error): default = {(:Exc) Exc.raise }
If the local address is available, `local_address` tail-calls $success with the `socket_address`.
If an IO error occurs, `local_address` tail-calls $error with an `exception`.
Preconditions
$success must be a function which takes a `socket_address`.
$error must be a function which takes an `exception`.
6.94.1.6. Serv.so_reuseaddr¶
`so_reuseaddr` returns a `ref` of a `bool` of SO_REUSEADDR option.
For usage of socket options, see the example program at the beginning of this module.
Precondition
The protocol family must be ipv4 or ipv6.
6.94.1.7. Serv.so_rcvbuf¶
`so_rcvbuf` returns a `ref` of a non-negative integer `num` of SO_RCVBUF option.
For usage of socket options, see the example program at the beginning of this module.
6.94.2. TCP_SERVER.open(...[Protocol_family=PROTOCOL_FAMILY.ipv6 $config={}])¶
`open` method makes a new listening socket.
Config methods:
• C.on_success($success): default = VAL.identity
• C.on_error($error): default = {(:Exc) Exc.raise }
• C.on_unsupported($unsupported): default = a function which tail-calls $error with an `exception`
If a listening socket is created, `open` tail-calls $success with a `tcp_server` of the listening socket.
If an IO error occurs, `open` tail-calls $error with an `exception`.
If the runtime does not support `Protocol_family`, `open` tail-calls $unsupported with no arg.
Preconditions
`Protocol_family` must be a `protocol_family`.
$success must be a function which takes a `tcp_server`.
$error must be a function which takes an `exception`.
6.94.3. TCP_SERVER.is?(Val)¶
`is?` method returns whether `Val` is a tcp_server.