Socket I/O

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.