|
This is a small examples of a server and clients.
The Server process listens on
a "public" request channel, ServerReq.
When a client makes a request and the server is free, the server sends
(ServerReq ! (ServeChan::QuitChan)
two "working" control channels to the client.
The server then either accepts messages to be processed
(ServeChan ? msg ->...)
from the client,
or (|)
accepts a notification (QuitChan ? x)
of the end of session, in which case
the working channels are discarded and it
goes back to listening on ServerReq.
In this way the sessions of two successive clients
can never overlap or interfere with each other.
The only bad behaviour that a client can exhibit
is to refuse to release the server.
(In this example the "service" is simply to copy
messages to standard output.)
A client makes a request by asking
(ServerReq ? ControlChans)
for a pair of working control channels.
It then uses the service for as long as necessary.
(In this example a client simply sends a couple of integers.)
The server and one or more clients are run in parallel (||).
let rec
ServerReq = chan, {public channel to request service}
Server =
let ServeChan = chan,
QuitChan = chan {2 new, secret channels}
in ServerReq ! (ServeChan::QuitChan) {respond to request} ->
let rec
Serve =
(ServeChan ? msg -> output ! msg{say} -> Serve |
QuitChan ? x {end of service} -> Server)
in Serve,
Client = lambda n.
ServerReq ? ControlChans {request begin service} ->
let SendChan = hd ControlChans,
QuitChan = tl ControlChans
in SendChan ! n {use service} -> SendChan ! (n+10) {etc} ->
QuitChan ! () {release server} ->
{any other stuff} stop
in Client 1 || Client 2 || Client 3 || Server
{\fB Server / Clients. \fP}
|
e.g. c1993
|
www #ad:
pfl...
| | |
choice |
|| | parallel |
-> | sequence |
? | input act |
! | output act |
chan | new channel |
|
|
|