![]() |
General Programming »
Threads, Processes & IPC »
Inter-Process Communication
Intermediate
Bridge Between Java And WindowsBy Xiangyang Liu 刘向阳Make your windows programs communicate with java programs easily |
Java, VC6, Java, Win2K, MFC, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
I have included some code that can make your windows
programs and your java programs communicate
with each other easily.� The emphasis is on the word easily,
because there could be a lot of different ways to do the same thing.�
On the windows side, I wrote an ActiveX
control called XYMessenger.� On the java
side, I wrote a java class also named XYMessenger.�
These two components have almost identical methods and they can send each
other messages of arbitrary size.� If the word XYMessenger
sounds familiar to you that is because I previously posted an article
on CodeProject about a client-server development tool package I wrote.�
The package is now free
(for commercial or non-commercial use) but the source code is not provided
to the public at this time.� The code provided here are simplified versions
of the key components in that package.� You can use and modify the
code anyway you wish if you acknowledge in your work that the original
idea is from me :-).
The basic idea is, if you insert the XYMessenger.ocx
control into your VB or MFC
program or other windows program that can
use an ActiveX control, then your program
can act as both client or server to other programs also using XYMessenger.�
For your java programs, you need only to derive
a class from the XYMessenger to achieve the
same goal.� A call to the ConnectDirect
method is all you need to join the communication.� The first program
to call ConnectDirect will be acting as the
root node in a tree called the communication tree.�
The root node needs to use a local port for other programs to connect to.�
Other programs will connect to this root node using the ip address and
the port number (of the root node).� These programs will be the clients
to the root node, however, each of them can also be a server so that more
and more programs can be connected together.
What can you do once you connected your programs
together?� Well, the SendTextMsg
method allows you to send messages of arbitrary size to other connected
programs.� How do you know who to send the message
to?� Each node in the communication tree is identified by a
user identifier of the form Name@XXX,
where Name is the login name used in the call
to ConnectDirect and XXX
is a digit string dynamically generated by the system to identify the position
of the node in the communication tree.�
The GetUserCount and GetUser
methods can be used to retrieve user identifiers of all nodes.� For
example, GetUser(0) will return the
user identifier of the first user in the internal user list, GetUser(-1)
will return the user identifier of the current node.� GetParent
will return the user identifier of the parent node of the current node.
What does a message look like?� A message has the following attributes:� Sender (user identifier), Receiver (user identifier), MsgID (integer), SenderMsgID (integer), Title, Text, and AppSpecificCode (integer).� The Sender, Receiver, Title, and Text fields are null terminated character strings in windows programs, and they are byte arrays in java programs.
Where are incoming messages stored and how to
retrieve and process them?� The incoming messages are stored
in an internal message array.� For windows
programs, an ActiveX event will be fired when
a new message arrives, the developer is supposed to implement an event
handler and process the message there.� For java
programs, the developer is supposed to override the virtual message handler
function in the base class XYMessenger to
process the message.� In both cases the message handlers will be invoked
by the system automatically.� The GetMsgCount method returns the total number of messages in the internal message
array.� There is an nMsgID parameter
in the message handler, you can use it to call the GetMsgIndex
method to obtain an index of the message.� This returned index can
be used to call GetMstTitle, GetMsgText,
GetMsgAppSpecificCode, etc.� The RemoveMsg
method destroys the message with given index.
The SendSyncTextMsg method is used to send
a synchronous message to a node.� It will not return until the receiver
has sent a reply message or time-out occurs.� You can specify the
time-out value (in seconds) with this method.� The method returns
a positive integer which can be used to call GetMsgIndexWithSenderMsgID
to obtain the index of the reply message.� If the receiver does not
reply or the method fails, then the return value will be -1.�
By the way, the message sent by SendSyncTextMsg
has to be replied by calling the ReplySyncTextMsg
method using the nSenderMsgID parameter
of the original message as the first parameter in the call. Please also note that the user implemented message handler will be called before
SendSyncTextMsg returns. If you delete all incoming messages from within the handler,
SendSyncTextMsg
will return -1 as if the receiver never replied to the sent message.
What if the data I want to send contains embedded
null characters (such a .exe file)?� Well, there is never a
problem if you only use the java component.�
For consistency, I wrote two functions, ReplaceNull
and RestoreNull in both java
and c++, that can be used to remove null characters
from data before sending the message and restore the null characters after
receiving the message.� The java version
is in class XYAPI, the c++
version is in file XYStatic.cpp.
I am very confident that the code and the basic ideas can be very useful
in general client-server programming, not just being a bridge between java
and windows programs.� In fact, I have
built pretty complicated server programs and have used XYMessenger
in both web clients (embedding XYMessenger
in applet) and web servers easily.� Please check my
web page for details.
For your convenience I have included the binary code in the zip file (the code size is extremely small).� Here are the steps to install:
CLASSPATH environment. XYTester.� This program tries
to send a message to each connected node and then broadcast a message to
all nodes every 3 seconds.� You can run multiple instances of this
program.� The command line to start the program is:
java XYTester ServerAddress ServerPort LocalPort
Note that if ServerPort is 0, then the instance will be the root node.� If LocalPort is 0, then the instance can only be a client (not accepting any connections).� Here is an example on using this program:
java�
XYTester� ""� 0� 5000java�
XYTester� ""� 5000� 0java� XYTester� ""� 5000�
5001java� XYTester ""� 5001� 0The windows sample program is called XYTreeDemo.�
It is a dialog based program.� Like XYTester,
you can use multiple instances of XYTreeDemo
to build the communication tree.� However,
this program has the capability of building multiple communication
trees within a single process.� If you start the program and
click the Create Node button, then a separate
user interface thread will be created with an instance of XYMessenger
embedded in a new dialog.� The Connect
button on the new dialog will call the ConnectDirect method to create a new node in a communication
tree.� This new node can be a client or a server (or both).�
After successfully connected, the Send button
will, of course, send a message to another node.� You can click the
Create Node button on the main dialog to create
as many nodes as possible.
Now the fun part, see what happens if you connect an instance of XYTreeDemo
to an instance of XYTester, or connect an
instance of XYTester to an instance of XYTreeDemo.
The ActiveX control XYMessenger.ocx
is implemented with VC++ 5.0 using the CSocket
class of MFC.� The java
class XYMessenger is implemented with JDK
1.2.2 using the Socket and ServerSocket
classes of java.net.
Each instance of XYMessenger.ocx can only be used in a single thread (apartment model threading).� As demonstrated by the XYTreeDemo program, you can use multiple instances of XYMessenger.ocx in multiple threads.� There is nothing to prevent you from using multiple instances of XYMessenger.ocx in a single thread.� Even if an instance of XYMessenger.ocx is waiting for a reply message from another node, the thread is not blocked, it can still process incoming messages from other nodes.
The java class XYMessenger
is truly multi-threaded in the sense that each connection (between two
nodes) is running in a separate thread.� Therefore, the user implemented
event handlers (virtual functions) have to be thread-safe even if you use
only one instance of XYMessenger.
The simplified code provided here has a hard coded limit of connecting at most 10 clients to a server (however, each of the 10 clients can have 10 clients connected to it).� It is not hard to increase the limit to, say 1000.� Another limitation is, each node in the communication tree maintains a list of user identifiers of all nodes.� This can be inefficient if there are hundreds of nodes connected together.� The free package on my web page does not have these limitations, of course, and it has a lot more functionality besides simply connecting programs together.
Thank you for reading this article.� Your input is appreciated.
14 June 2002
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 13 Jun 2002 Editor: Chris Maunder |
Copyright 2001 by Xiangyang Liu 刘向阳 Everything else Copyright © CodeProject, 1999-2009 Web18 | Advertise on the Code Project |