library(sockets)
This library package defines a number of predicates for communicating over sockets.
To create a (bi-directional) stream connected to a remote server,
use socket_client_open/3
.
To open a port for remote clients to connect to, use
socket_server_open/[2,3]
and to open a stream to a connecting
client, use socket_server_accept/4
.
To be able to multiplex input and output from several streams (not
necesessarily socket streams) and incoming connections, use
socket_select/7
.
When opening a client or server socket a socket address needs to be specified. The address specifies the address family and family-specific information. The following formats are supported for socket addresses:
inet(
Nodename,
Servname)
:
ServnameAF_INET
or AF_INET6
).
Nodename is the internet address of the remote host, as an
atom, something like 'www.sics.se'
or
'193.10.64.51'
. The empty nodename ''
(the default),
has special meaning, see the documentation for
socket_client_open/3
and socket_server_open/[2,3]
.
Servname is either a port number as an atom of decimal
digits or as an integer, e.g. '80'
, or 80
;
alternatively some well known port names can be used, e.g.
'http'
. The set of well known port names is OS specific,
portable code should use integer port numbers.
Servname can also be a variable when opening a server socket
with socket_server_open/[2,3]
. In this case a available
port is assigned automatically and Servname is bound to it.
unix(
Path)
AF_UNIX
) socket is opened at the specified
file system location. This is only supported on Unix-like
platforms.
Path is a file-name and is passed to
absolute_file_name/2
. There may be platform-specific
restrictions on the length of the resulting pathname and the file
system containing it.
All streams below can be read from as well as written to. All I/O
predicates operating on streams can be used, for example
get_code/2
, get_byte/2
,
read/2
, write/2
, format/3
,
current_stream/3
,
etc. The predicates that create streams take options similar to
open/4
, e.g. to specify whether the stream is binary
(the default) or text.
socket_client_open(
+Addr,
-Stream,
+Options)
''
) then a connection is made to the local machine.
The stream is created using options from Options. Supported options include:
type(binary)
type(text)
eof_action(
Action)
open/4
.
encoding(
ENCODING)
type(text)
.
eol(
Eol)
type(text)
.
To create a binary stream to some web server www.sics.se
, you
would do e.g.
| ?- socket_client_open('www.sics.se':80, Stream, [type(binary)]).
or, to make a text (Latin 1)
stream to a daytime
service in Hong Kong you could do:
| ?- socket_client_open('stdtime.gov.hk':daytime, S, [type(text)]), read_line(S, L), format('~s', [L]).
See the source code for library('linda/client')
for a
simple client.
socket_server_open(
?Addr,
-ServerSocket,
+Options)
''
) then any remote client machine is allowed to
connect unless the option loopback(true)
is also specified.
Addr
can specify an internet address where the port is a variable in
which case a free port number is used and Port is bound to
it. The common case is that Addr is a numeric port number or a
variable that becomes bound to a free port number.
The created server socket should be closed with
socket_server_close/1
eventually. Incoming connection can
be accepted
with socket_server_accept/4
and waited for with
socket_select/7
.
See the source code for library('linda/server')
for a
simple server that uses this predicate.
Options is a list of options, currently
reuseaddr(Bool)
true
or false
(the default). If
true
then allow reuse of local addresses. For internet
sockets this corresponds to the SO_REUSEADDR
socket
option. For unix domain sockets this means that the file will be
deleted, if present, before opening.
numeric_nodename(Bool)
true
or false
(the default). If
true
then the nodename of an internet address will be
treated as a numerical address and no name lookup will be
performed.
numeric_servname(Bool)
true
or false
(the default). If
true
then the servname of an internet address will be
treated as a numerical port number and no lookup of well
known port names will be performed.
loopback(Bool)
true
or false
(the default). If
true
then the nodename will be ignored and the socket will
only listen to connection from the loopback device, i.e. the
local machine.
socket_server_open(
?Port,
-ServerSocket)
socket_server_open(
Port,
ServerSocket, [])
.
socket_server_accept(
+ServerSocket,
-Client,
-Stream,
+StreamOptions)
socket_client_open/3
. Client will be unified with an atom containing
the numerical Internet host address of the connecting client.
Note that the stream will be type(binary)
unless
type(text)
is specified either explicitly or implicitly
with encoding/1
or other text-only options.
socket_server_close(
+ServerSocket)
socket_select(
+ServerSockets,
-SReady,
+ReadStreams,
-RReady,
+WriteStreams,
-WReady,
+Timeout)
socket_server_accept/4
), streams on ReadStreams
ready for input, and streams on WriteStreams
ready for output. The streams can be any kind of streams, they need
not be socket streams. The ready server sockets are returned (in the same
order) in SReady, the ready input streams in RReady,
and the ready output streams in WReady.
An input (output) stream is ready for input (output) when an item can be read (written) without blocking. An item is a character for text streams and a byte for binary streams. Note that a stream is considered ready for I/O if the corresponding I/O operation will raise an error (such as if the stream is past end of stream).
Each entry in the input lists ServerSockets,
ReadStreams, and WriteStreams can be either a server
socket or stream respectively or a term
Term-
Entry where Entry is the server
socket or stream and Term is some arbitrary term used for
book-keeping. If an entry is associated with a term in this way
then so will the corresponding ready entry.
If TimeOut is instantiated to off
, the predicate
waits until something is available. If TimeOut is a nonzero
number (integer or floating point), then the predicate waits at
most that number of seconds before returning. For backward
compatibility, if TimeOut is S:U the predicate waits
at most S seconds and U microseconds. If there is a
timeout, all ready lists are unified with []
.
See the source code for library('linda/server')
for a
simple server that uses this predicate.
current_host(
?HostName)