In gotAMessage(), you see the other half of the functionality, where we add a client to the list of clients waiting for data (if it's a MT_WAIT_DATA message), or we match up a client with the message that just arrived (if it's a MT_SEND_DATA message). Note that for simplicity we didn't add a queue of clients that are waiting to send data, but for which no receiver is yet available—that's a queue management issue left as an exercise for the reader!
/*
* gotAMessage
*
* This routine is called whenever a message arrives. We
* look at the type of message (either a "wait for data"
* message, or a "here's some data" message), and act
* accordingly. For simplicity, we'll assume that there is
* never any data waiting. See the text for more discussion
* about this.
*/
void
gotAMessage (int rcvid, ClientMessageT *msg)
{
int i;
// determine the kind of message that it is
switch (msg -> messageType) {
// client wants to wait for data
case MT_WAIT_DATA:
// see if we can find a blank spot in the client table
for (i = 0; i < MAX_CLIENT; i++) {
if (!clients [i].in_use) {
// found one -- mark as in use, save rcvid, set timeout
clients [i].in_use = 1;
clients [i].rcvid = rcvid;
clients [i].timeout = 5;
return;
}
}
fprintf (stderr, "Table full, message from rcvid %d ignored, "
"client blocked\n", rcvid);
break;
// client with data
case MT_SEND_DATA:
// see if we can find another client to reply to with
// this client's data
for (i = 0; i < MAX_CLIENT; i++) {
if (clients [i].in_use) {
// found one -- reuse the incoming message
// as an outgoing message
msg -> messageType = MT_OK;
// reply to BOTH CLIENTS!
MsgReply (clients [i].rcvid, EOK, msg,
sizeof (*msg));
MsgReply (rcvid, EOK, msg, sizeof (*msg));
clients [i].in_use = 0;
return;
}
}
fprintf (stderr, "Table empty, message from rcvid %d ignored, "
"client blocked\n", rcvid);
break;
}
}