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.