|
Basic Event Concepts
by Binh Ly
If a client talks to a server through the server's interface, wouldn't it
make sense that the server can also talk to the client through the client's
interface? But wait, we never mentioned anything before about clients having any
interfaces have we?
Let's look at it from another angle. If we reversed the roles for client and
server in such a way that the server became the client and the client became the
server, then the server now talks to the client in the normal client-to-server
manner.

Figure: Client-to-server and
server-to-client connection
In order for a client to become a server of the server, it has to expose an
interface to the server. Once the server gets an interface from the client, it
can then call any methods on the interface as if the client was its server. Got
it? If not, read the last two statements three more times.
The idea is really simple: the client hands out an interface to the server.
Whenever the server wants to chit-chat with the client, the server simply uses
the interface it got from the client to call back into the client. To do this,
the server must provide a method in its interface allowing the client to pass
the client's interface into the server. Using our example on the Downloader
object, the IDownloader interface must somehow provide a mechanism for a client
to hand its interface to Downloader. One way to do this is:
IDownloader = interface
procedure HereYouGo (ClientInterface);
procedure GetFile (FileName);
end;
The client can then pass its interface to Downloader using
pseudocode like
this:
// create Downloader object
Downloader = CreateObject ("DownloaderServer.Downloader");
// pass client's interface into Downloader
Downloader.HereYouGo (MyInterface);
// perform download
Downloader.GetFile (HugeFileFromInternet);
To complete our Downloader object, assume that the client exposes this
interface:
IDownloadListener = interface
procedure UpdateProgress (Percent);
end;
Given IDownloadListener, IDownloader can now be implemented like this:
procedure Downloader.HereYouGo (ClientInterface);
begin
Store ClientInterface in a DownloadListener local/object variable
end;
procedure Downloader.GetFile (FileName);
begin
while (NotDoneDownloadingYet) do
begin
DownloadMoreBytes;
// notify client (IDownloadListener) of progress
DownloadListener.UpdateProgress (CalculateDownloadedPercentageSoFar);
end;
end;
Very simple isn't it?
Sometimes, it is necessary for several clients to connect to a single object
so that they all receive events from that object. Consider a JazzChatRoom server
object that represents a chat room for people who are interested in jazz music.
Chatters (chat clients) who are interested in jazz can all meet in one JazzChatRoom - this means that all chat clients connect to one JazzChatRoom
object.

Figure: Multiple chatters
connecting to one JazzChatRoom
Now, if one of the chatters says something, it is JazzChatRoom's
responsibility to broadcast what that chatter said to the rest of the crew. In
other words, JazzChatRoom needs to maintain a list of (possibly more that one)
clients so that it can call into each one of its clients when it needs to
broadcast a
chatter's message.
Based on this, here's one implementation of
JazzChatRoom:
// client's interface
IChatter = interface
procedure HeresAMessageFromFellowChatter (Message);
end;
// server's interface
IJazzChatRoom = interface
procedure EnterChatRoom (Chatter);
procedure BroadcastMessage (Message);
end;
procedure JazzChatRoom.EnterChatRoom (Chatter);
begin
Store Chatter into a Chatters list
end;
procedure JazzChatRoom.BroadcastMessage (Message);
begin
// iterate chatter list and notify each chatter
For each Chatter in Chatters list
Chatter.HeresAMessageFromFellowChatter (Message);
end;
A chatter who wishes to join the chat
room would simply call EnterChatRoom to register itself into JazzChatRoom's
client list:
// find JazzChatRoom instance and join it
JazzChatRoom = FindJazzChatRoom;
JazzChatRoom.EnterChatRoom (MyIChatterInterface);
And then when a chatter wishes to broadcast a
message to his fellow chatters, he can simply say:
JazzChatRoom.BroadcastMessage
("Hello World!");
Based on JazzChatRoom's BroadcastMessage
implementation above, the message will be sent to all chatters (including the
broadcaster) through each chatter's IChatter interface.
Where Are We?
I've just shown you the concept of role-reversal between client and server.
In COM, it is absolutely possible for a client to give the server its interface
making it a server of the server. Note how I use the term
"role-reversal" here. As you shall see later, you'll encounter COM
security issues that are explained in the context of client-to-server
communication. When dealing with security issues, always remember that when the
server calls back into the client, the server becomes a client and the client
becomes a server.
Further Reading
- Understanding ActiveX and OLE by David
Chappell
- Essential COM by Don Box
|