This is a minor extension of EchoServer: when started, it expects an integer command line argument maxClients, denoting the maximal number of concurrently served clients. If more clients connect, they are just informed that the server is busy and disconnected.
module EchoServer2 where
import POSIX
import Counter
port = Port 12345
root w = do
env = new posix w
clients = new counter
case parse (env.argv ! 1) of
Right n -> env.inet.tcp.listen port (server n clients env.stdout)
_ -> env.stdout.write "usage: EchoServer n, where n is number of concurrent clients\n"
env.exit 1
server maxClients clients logfile sock = class
n := 1
p = show sock.remoteHost
log str = logfile.write ('[':str ++ "]\n")
echo str = action
sock.outFile.write (show n ++"> "++str)
n := n+1
close = request
clients.decr
log (p ++ " closing")
result ()
neterror str = action log ("Neterror: "++str)
established = action
cl <- clients.value
if cl < maxClients then
clients.incr
log ("Connected from " ++ p)
sock.inFile.installR echo
else
sock.outFile.write "Server busy"
log ("Refused " ++ p)
sock.close
result Connection{..}
We need to keep track of the number of served clients. For this we use a Counter object, created by the root object.
When a new client connects, the counter value is retrieved and only if this value is small enough is an echo action installed; otherwise the client is informed that the server is busy and the socket closed. When a client closes the connection, the counter is decreased.
A Counter object is appropriate here, since several server objects, each interacting with one client, interacts with it. In contrast, the line number local to each server object is maintained in a simple integer state variable.