[Copyright]
[Table of Contents]
The Ideas Behind XYSystem
Let's see an example in the traditional client-server environment. Suppose program A is a server, program B and program C are clients that use services implemented by program A. First there must be a way for program B and program C to "connect" to program A. What if program B is also a server with its own clients, program D and program E? Program D and program E have to "connect" to program B somehow. What if the clients of program B also need to call services implemented in program A? In that case we need only to "connect" to program A from program D and program E.
Even though the situation gets more complicated, it is still possible to handled it the traditional way given enough time and resources. However, there is a simpler and better way. Within a Win32 program, we can use the SendMessage and the PostMessage functions to communicate among different parts of the program and to activate some predefined procedures. Wouldn't it be nice to implement the same feature across processes and across machines?
In XYSystem, every process involved need only to connect to the system once. Any connected process can send/receive messages to/from any other connected process. Calling a service in a server is equivalent to sending a synchronous message to the server. This makes it easier for two processes to communicate with each other. What about event notification? It can be done by an asynchronous message from the server process to the client process. It is also possible to broadcast messages to a group of connected processes. Please note that XYSystem does a lot more than the Win32 functions SendMessage and PostMessage. For instance, you can send data of arbitrary size across processes in XYSystem.
Wait a minute! How does XYSystem achieve this? Does it have one or more large server programs running in the background acting as message brokers? Does it have a central database to store system and user messages? These are the issues that may cause concern.
There is no central server provided by XYSystem for the above purposes. The work of dispatching or forwarding messages is distributed among all connected processes. Actually, the work is done by the XYMessenger object embedded in each connected process so that no additional programming is required for the users to send and receive messages. Each process connected to the system is a node in a tree structure. XYSystem does provide an extremely small program to act as the root node which implements the default user authentication.
Ok, that's nice. But how to implement a service via messages? For example, a specific service returns an array of floating-point numbers and takes two string input arguments and one integer input argument. How can it be done via messages? What if the types of the arguments or return data are complicated data objects? How is this handled by XYMessenger?
Actually, this is not XYMessenger's job. XYMessenger handles only the connection to the system and the sending and receiving of messages between connected processes. XYSystem provids other very small and easy to use tools to pack a data object into a message and to unpack the data object from the message when it reaches the destination. See the topic sending objects over the network for more details.
Isn't it wonderful?
XYSystem Messages
As we described previously, the communiction among XYMessenger objects are supported by messages. There are only two types of messages that concern application developers and application users, Text Message and Binary Message. These messages can be sent synchronously or asynchronously. They can be sent to a specific node represented by a given user identifier in the communication tree, or they can be broadcasted to a group of nodes.
XYMessenger will invoke the corresponding user-defined event handler automatically when a message is received. The receiver can reply by sending a message to the original sender. Note that a node in the communication tree cannot send a message to itself.
Messages from other nodes in the communication tree are stored in an internal list of the XYMessenger object. Various methods are provided to access and modify the messages. Here is how to retrieve messages.
The message notification events generated by the system have the nMsgID and the nSenderMsgID parameters. Call the GetMsgIndex method using the nMsgID parameter, or call the GetMsgIndexWithSenderID method using the nSenderMsgID parameter, to get the index of the message in the internal message list. Then use this index to retrieve message data fields.
A text message consists of the following fields: message id, sender message id, user identifier for the sender, user identifier for the receiver, title field, text field, and an integer app specific code. Call the SendTextMsg and SendSyncTextMsg methods to send a text message to a specific node in the communication tree. Call the BroadcastTextMsg method to send the message to either all nodes in the communication tree or only descendent nodes of the current node.
The XYTextMsg and XYTextMsgBroadcast event handlers invoked automatically by the system to process incoming text messages. The GetMsgTitle method is used to retrieve the title field of the message and the GetMsgText method is used to retrieve the message body.
The title and the text fields do not have to be simple strings, they can represent complicated objects with the help of XYTextCarrier, a tools included in this package.
A binary message consists of the following fields: message id, sender message id, user identifier for the sender, user identifier for the receiver, data size, binary data block, and an integer app specific code. Call the SendBinaryMsg and SendSyncBianryMsg methods to send a binary message to a specific node in the communication tree. Call the BroadcastBinaryMsg method to send the message to either all nodes in the communication tree or only descendent nodes of the current node.
The XYBinaryMsg and XYBinaryMsgBroadcast event handlers invoked automatically by the system to process incoming binary messages. The GetMsgSize method is used to retrieve the size of the binary message and the GetMsgData method is used to retrieve a pointer to the message data.
By utilizing the nAppSpecific field in these two types of messages, you can define as many subtypes as possible. Note that negative values for this parameter are reserved for system use. It is recommended that the value 0 is used for this parameter in applications that do not need (or care about) this field.