6.2 Server applications
The typical sequence for generating a server application is given below. To close the server, use close/1 on AcceptFd.
create_server(Port) :- tcp_socket(Socket), tcp_bind(Socket, Port), tcp_listen(Socket, 5), tcp_open_socket(Socket, AcceptFd, _), <dispatch>
There are various options for <dispatch>. The most commonly used option is to start a Prolog thread to handle the connection. Alternatively, input from multiple clients can be handled in a single thread by listening to these clients using wait_for_input/3. Finally, on Unix systems, we can use fork/1 to handle the connection in a new process. Note that fork/1 and threads do not cooperate well. Combinations can be realised but require good understanding of POSIX thread and fork-semantics.
Below is the typical example using a thread. Note the use of setup_call_cleanup/3 to guarantee that all resources are reclaimed, also in case of failure or exceptions.
dispatch(AcceptFd) :- tcp_accept(AcceptFd, Socket, _Peer), thread_create(process_client(Socket, Peer), _, [ detached(true) ]), dispatch(AcceptFd). process_client(Socket, Peer) :- setup_call_cleanup( tcp_open_socket(Socket, StreamPair), handle_service(In, StreamPair), close(StreamPair)). handle_service(StreamPair) :- ...