This library package defines a number of predicates manipulating
sockets. They are all rather straight-forward interfaces to the
corresponding BSD-type socket functions with the same name (except
current_host/1
). The reader should therefore study the
appropriate documents for a deeper description.
The Domain is either the atom 'AF_INET'
or
'AF_UNIX'
. They correspond directly to the same domains in
BSD-type sockets. 'AF_UNIX'
may not be available on non-UNIX
platforms.
An Address is either 'AF_INET'(Host,Port)
or
'AF_UNIX'(SocketName)
. Host is an atom denoting a
hostname (not an IP-address), Port is a portnumber and
SocketName is an atom denoting a socket. A reader familiar
with BSD sockets will understand this immediately.
All streams below can be both read from and written on. All I/O
predicates operating on streams can be used, for example
read/2
, write/2
, format/3
, current_stream/3
,
etc. Socket streams are block buffered both on read and write by
default. This can be changed by calling socket_buffering/4
.
To load the package, enter the query
| ?- use_module(library(sockets)).
socket(
+Domain,
-Socket)
A socket Socket in the domain Domain is created.
socket_close(
+Socket)
Socket is closed. Sockets used in socket_connect/2
should
not be closed by socket_close/1
as they will be closed when the
corresponding stream is closed.
socket_bind(
+Socket, 'AF_UNIX'(
+SocketName))
socket_bind(
+Socket, 'AF_INET'(
?Host,
?Port))
The socket Socket is bound to the address. If Port is
uninstantiated, the operating system picks a port number to which
Port is bound.
socket_connect(
+Socket, 'AF_UNIX'(
+SocketName),
-Stream)
socket_connect(
+Socket, 'AF_INET'(
+Host,
+Port),
-Stream)
The socket Socket is connected to the address. Stream is a
special stream on which items can be both read and written.
socket_listen(
+Socket,
+Length)
The socket Socket is defined to have a maximum backlog queue of
Length pending connections.
socket_accept(
+Socket,
-Stream)
socket_accept(
+Socket,
-Client,
-Stream)
The first connection to socket Socket is extracted. The
stream Stream is opened for read and write on this
connection. For the 'AF_INET'
domain, Client will be
unified with an atom containing the Internet host address of
the connecting entity in numbers-and-dots notation. For other domains,
Client will be unbound.
Under Windows socket_accept/[2,3]
is not interruptible. This will
prevent the process from terminating or responding to keyboard
interrupt. A workaround is to use socket_select/5
with a timeout,
something like:
%% same as socket_accept/3 but will be interruptible with CTRL-C, %% CTRL-BREAK etc (within 2 seconds) nonblocking_socket_accept(Socket, Client, Stream) :- Seconds = 2, % wait this long between retries MicroSeconds = 0, TimeOut = Seconds:MicroSeconds, repeat, % repeat until connection or error socket_select([accept-Socket], Accepted, TimeOut, [], _ReadStreams), %% Here Accepted == [] if the timeout period expired Accepted = [accept-connection(Client1, Stream1)], !, Client = Client1, Stream = Stream1.
socket_buffering(
+Stream,
+Direction,
-OldBuf,
+NewBuf)
The buffering in the Direction of the socket stream
Stream is changed from OldBuf to NewBuf.
Direction should be read
or write
. OldBuf and
NewBuf should be unbuf
for unbuffered I/O or fullbuf
for block buffered I/O.
socket_select(
+TermsSockets,
-NewTermsStreams,
+TimeOut,
+Streams,
-ReadStreams)
The list of streams in Streams is checked for readable
characters. The list ReadStreams returns the streams
with readable data. Under Windows, only socket streams can be used
with socket_select
. Under UNIX, a stream can be any
stream associated with a file descriptor but
socket_select/5
may block for non-socket streams even
though there is data available. The reason is that non-socket
streams can have buffered data available, e.g. within a C
stdio
FILE*
.
socket_select/5
also waits for connections to the sockets
specified by TermsSockets. This argument should be a
list of Term-Socket pairs, where Term,
which can be any term, is used as an
identifier. NewTermsStreams is a list of
Term-connection(
Client,
Stream)
pairs,
where Stream is a new stream open for communicating with a
process connecting to the socket identified with Term,
Client is the client host address (see socket_accept/3
).
If TimeOut is instantiated to off
, the
predicate waits until something is available. If TimeOut is
S:U
the predicate waits at most S
seconds and
U
microseconds. Both S
and U
must be integers >=0.
If there is a timeout, ReadStreams and NewTermsStreams are
[]
.
socket_select(
+Sockets,
-NewStreams,
+TimeOut,
+Streams,
-ReadStreams)
socket_select(
+Socket,
-NewStream,
+TimeOut,
+Streams,
-ReadStreams)
socket_select(
+Sockets,
-NewStreams,
-NewClients,
+TimeOut,
+Streams,
-ReadStreams)
socket_select(
+Socket,
-NewStream,
-NewClient,
+TimeOut,
+Streams,
-ReadStreams)
These forms, which are provided for backward compatibility only, differs in how sockets are specified and new streams returned.
socket_select/[5,6]
also wait for connections to the sockets in
the list Sockets. NewStreams is the list of new
streams opened for communicating with the connecting
processes. NewClients is the corresponding list of client
host addresses (see socket_accept/3
).
The second form requires one socket (not a list) for the first
argument and returns a stream, NewStream, if a
connection is made.
current_host(
?HostName)
HostName is unified with the fully qualified name of the
machine the process is executing on. The call will also succeed if
HostName is instantiated to the unqualified name of the
machine.
hostname_address(
+HostName,
-HostAddress)
hostname_address(
-HostName,
+HostAddress)
The Internet host is resolved given either the host name or address. HostAddress should be an atom containing the Internet host address in numbers-and-dots notation. The predicate will fail if the host name or address cannot be resolved.