30 Sep — D Web server, cont'd
We previously saw a Web server built in D. It creates a new thread for every client, but real Web servers will have a threshold of how many clients they'll deal with simultaneously, since more clients will just bog down server performance without actually improving the server success.
So now we ask: How can we modify this Web server to include such a threshold, say at most 10 clients at any time?
Approach A — counter in main
So that main
knows when a client is done,
we modify the respond
function to include a line
saying “send(callerTid, -1)
” just before
“socket.close();
”. Then we modify main
to maintain a counter.
void main() {
Tid cacheTid = spawn(&cacheServer);
Socket server = new TcpSocket;
server.bind(new InternetAddress(httpPort));
server.listen(10);
int numAlive = 0;
while (true) {
clientSocket = cast(shared Socket) server.accept();
// Update numAlive based on any outstanding messages
bool received = true;
while (received) {
received = false;
receiveTimeout(dur!"msec"(0),
(int completed) { --numAlive; received = true; }
);
}
if (numAlive < 10) {
spawn(&respond, thisTid, cacheTid);
numAlive++;
} else {
spawn(&sendServerBusy, thisTid);
}
// Wait until client is done with "clientSocket." But we
// some threads may complete their work first.
bool clientStarted = false;
while (!clientStarted) {
receive(
(bool started) { clientStarted = true; },
(int completed) { numAlive--; }
);
}
}
}
Approach B — counter in separate thread
Alternatively, we could have a separate thread that maintains
the counter, akin to the cacheServer
function.
This would be a “purer” message-passing technique.
void countServer() {
int count = 0;
while (true) {
receive(
(Tid tid) { send(tid, count); }, // request current count
(int delta) { count += delta; } // update current count
);
}
}
We would have to modify main
as follows.
void main() {
Tid cacheTid = spawn(&cacheServer);
Tid countTid = spawn(&countServer);
Socket server = new TcpSocket;
server.bind(new InternetAddress(httpPort));
server.listen(10);
while (true) {
clientSocket = cast(shared Socket) server.accept();
send(countTid, thisTid);
if (receiveOnly!int() < 10) {
spawn(&respond, thisTid, cacheTid, countTid);
send(countTid, 1); // increment client count
} else {
spawn(&sendServerBusy, thisTid);
}
receiveOnly!bool(); // don't continue until thread got clientSocket
}
}
Finally, we'd need to modify respond
to decrement the
count once it is complete. We'd add a new parameter to respond
named countTid
, so that respond
knows who
to notify once it is done. (Note that we modified main
to pass this
parameter into respond
.)
Then we modify respond
function to include the line
“send(countTid, -1)
” just before
“socket.close();
”.