We haven't talked about the various parameters in the
examples above so that we could focus just on the message passing.
Now let's take a look.
More about channels
In the server example above, we saw that the server created just one channel. It could certainly have created more, but generally, servers don't do that. (The most obvious example of a server with two channels is the Transparent Distributed Processing (TDP, also known as Qnet) native network manager—definitely an odd piece of software!)
Who sent the message?
Often a server will need to know who sent it a message. There are a number of reasons for this:
Replying to the client MsgReply() accepts a receive ID, a status, a message pointer, and a message size. We've just finished discussing the receive ID; it identifies who the reply message should be sent to. The status variable indicates the return status that should be passed to the client's MsgSend() function. Finally, the message pointer and size indicate the location and size of the optional reply message that should be sent.
Not replying to the client
There's absolutely no requirement that you reply to a client before accepting new messages from other clients via MsgReceive()! This can be used in a number of different scenarios.
Replying with no data, or an errno
When you finally reply to the client, there's no requirement that you transfer any data. This is used in two scenarios.
Finding the server's ND/PID/CHID
You've noticed that in the ConnectAttach() function, we require a Node Descriptor (ND), a process ID (PID), and a channel ID (CHID) in order to be able to attach to a server. So far we haven't talked about how the client finds this ND/PID/CHID information.
What about priorities?
What if a low-priority process and a high-priority process send a message to a server at the same time?
Reading and writing data
So far you've seen the basic message-passing primitives. As I mentioned earlier, these are all that you need. However, there are a few extra functions that make life much easier.