Last time, we looked at lots of UNIX software for Windows/NT, and I provided my own Goodie in the form of a recursive command executor. (BTW, I made an error in my critique of the NT “DEL” command—turns out it does support the /S option for subdirectory support!) This time, we’ll look at some free ORBs that are out there, as well as how my free Telnet server is coming along.
My goal here is twofold: For managers and marketers new to CORBA, I want to introduce the technology. Your company can use the proven CORBA development model to build new client/server applications. For programmers, I want to give a taste of the many options available for CORBA development. Many commercial ORBs are large, cumbersome, and expensive. It can actually be a time-saver to find a reliable freeware ORB that allows you to write code quickly. And by choosing your ORB carefully, you can minimize the amount of recoding you must perform if you change to a different OS. For example, the DNS (not Domain Name Services!) commercial ORB runs only on OS/2. If you write an application that uses many DNS-specific features, you’ll find it harder to port your code to, say Solaris. But by choosing a free ORB implementation (with source code) that’s easily portable to different platforms, you can help insulate your application from such company policy decisions.
To aid this approach, I’ve addressed the following for each reviewed ORB:
1. What does it take to install the ORB? How easily can the ORB be built (98 and NT only)? The goal here is to get an idea of how easy it is to build the ORB on an arbitrary machine, which is one indicator of the relative ease for moving the ORB to a different platform (at least, in theory…). My compiler is Visual C++ 6.0. By default, I do all builds on a Windows/98 box, and switch to a Windows/NT 4.0 (Client) box only if the compilation produces errors.
2. What does it take to run the ORB? Does it require special setup or configuration files?
3. Do the included sample programs for the ORB actually work? I’ve found this to be the best indicator for how well thought out a system is. I’m constantly amazed at the number of samples that simply don’t work after I’ve downloaded/built them per instructions. That tells me a lot about whether my own efforts with a package are likely to be successful.
Let’s start with a quick primer on ORBs and CORBA. An ORB is an Object Request Broker, while CORBA stands for Common Object Request Broker Architecture (developed by the Object Management Group, or OMG, at http://www.omg.org). In a nutshell, an ORB is a piece of software that services user requests, while CORBA is a standard about how the ORB should work (much like the difference between the ANSI C standard and a C compiler).
CORBA is so popular now because it standardizes a common problem: How do you implement a distributed application? In the old days (which, BTW, are still here) software vendors would make up their own data protocol for issuing remote requests over a TCP/IP connection. Or, a software vendor would use a language-specific helper such as RPC (Remote Procedure Call) to enable intra-machine function calls. The problem with multiple protocols is that a client application required intimate knowledge of a vendor’s data protocol to issue the remote requests. And the problem with RPC is that only C supports it in a standard and robust fashion. Thus enter CORBA and an ORB.
Conceptually, an ORB sits between an application program and a software provider. For example, assume that you’re developing a Web e-Mall application. This e-Mall consists of customers, shops, and some common database statistics for all shops (customers serviced, average wait time, etc.). Furthermore, each shop can have one or more Web servers to help balance traffic load. And all these shops require common database functions that must be synchronized to some degree. To access the common database functions, each “shop” issues requests to an ORB. In turn, the ORB invokes the software that can handle the request. Thus, the ORB exists as a broker, since it does nothing more than manage requests and responses between a client and a software provider. Moreover, the ORB guarantees that the data passed between client and software provider is transported in a platform and language neutral fashion!
In actual fact, you’ll see two different ways for implementing a CORBA application. Some ORBs, such as the Jaguar Server ORB (Sybase), exist as a separate application that invokes user programs to satisfy client requests. Other ORBs, such as the free Engine Room CORBA (described below), allow you to link the ORB code directly into your application. In effect, your application serves as both the ORB and the ORB component.
CORBA introduces some new terminology, including packages, naming services, components, and IDL (Interface Definition Language). Packages refer to a group of functions or services that a particular software producer registers with the ORB, while component refers to the piece of software that the ORB invokes when a request arrives for a function in a given package. The software provider defines the packages it supports by using an IDL file (which, in turn, requires an IDL compiler—one comes with each CORBA implementation). The IDL file allows the software producer to define the various functions and data types it provides to the ORB. Also, the IDL compiler transforms the IDL file into language-appropriate files (such as .h for C, or .java files for Java) that both the software producer and the client program can use. Inside the client program, CORBA requests look like any other function call. And inside the component, the function implementation looks like any other function implementation. The magic is that the client program and the software producer’s server program can exist on separate machines, and the ORB (along with the code generated by the IDL compiler) handles turning the function requests into a network call with response data (much like the Remote Procedure Call interface, or RPC).
Client applications issue requests to the ORB by using naming services, which allow the client application to locate a particular ORB. (Once the client locates the ORB, the client uses a process called narrowing to get references to specific packages and methods the ORB supports.) The client issues requests to the ORB using a special protocol called the Internet Inter-ORB Protocol, or IIOP (at least when referencing the ORB using the Internet).
One confusing thing when talking about ORB components is that they’re often called servers (I called one of my own Java ORB components that, for example). It’s confusing because the ORB itself is a server. When the ORB is itself a separate application, it listens on a TCP/IP port (almost always a configurable parameter) for requests from the client. When a request comes in, the ORB automatically sends the request on to the software producer’s server. To keep it simple, remember that (in CORBA terms), server generally refers to the ORB component that knows how to satisfy a specific request from a client. To add to the confusion, a CORBA client can also itself be a CORBA component that services requests from other clients…but I think I’ve gone on long enough here!
The best place to get an ORB for prototype work is from The Free CORBA Page at http://adams.patriot.net/~tvalesky/freecorba.html. Not only do you get a long list of free ORBs, you also get a handy matrix that compares and contrasts different ORBs (both commercial and free). I chose a few of the more promising looking ORBs out of the list, although you may find that other ORBs more closely fit your needs
With a name like that, I expected a terse and gritty ORB implementation. While that was true, I also got a complete ORB implementation (with an IDL compiler) weighing in at just 330KB! The whole thing built in a matter of a minute, although the setup was a little more demanding than for the OmniORB (below). Specifically, you must edit the environment script files and the compiler makefiles to match your machine setup. That done, it took less than 3 minutes for me to build the entire ORB!
The ORB itself can run as either a Java application or as a C application (if you built the C application). I ran the ORB (it fired up immediately), and then I ran the sample C program. The sample C programs exercises many of the default data types, as well as sending/receiving user-defined data types to/from the ORB component. Everything ran without problems, and configuration was simple (you set a couple of environment variables to set the ORB listening port).
From what I saw, there are no naming services per se; rather, client applications (and server components) simply receive the host and port number of the ORB and use that to start direct communications with the ORB. Depending on your development needs, this may not be a problem (it certainly makes program development simple). However, be aware that other ORB implementations aren’t nearly as simple to use. So if ORB portability is your goal, then you may not wish to use the Engine Room.
For simplicity and ease-of-use, I have to say this package is a winner!
AT&T bought Olivetti Research and renamed it AT&T Laboratories in Cambridge (England, not Massachusetts). (You can reach them at http://www.uk.research.att.com/software.html.) They boast they have (possibly) the fastest CORBA implementation available—and they have some benchmark results (http://nenya.ms.mff.cuni.cz/thegroup/) that seem to back up that claim. The binary download was big (weighing in just over 8MB), so I downloaded only the source (more appealing at 1.5MB).
To compile, you also need the GNU Win32 Unix utilities from Cygnus (featured in the last column). As an alternative to the whole GNU package, you can get a stripped down version from ftp://ftp.uk.research.att.com/pub/omniORB/gnu-win32-lite.zip. You’ll need to read the readme.win32 in the instructions for detailed help on building the package—however, note that you can call the Microsoft VCVARS32.BAT batch file to set the system variables LIB and INCLUDE appropriately (not mentioned in the readme file).
I must say I was impressed with the make process—there was some serious work put into the makefile. On my machine (a Win98 box at 350mHz with 160MB RAM, running Visual C++ 6.0) I got a nasty KERNEL32 General Protection fault about halfway through the process. So, I switched over to my NT box, mounted the drive where I had the source files, and ran the make again. This time, everything worked just fine. On the down side, the build process took about 65 minutes (on a relatively fast machine), so it’s probably just as well to download a full package (with binaries and source code).
OmniORB is an industrial-strength product. As such, it’s less concerned with total ease-of-use than with providing lightning fast response speed. The practical implication is a slightly more complex installation for the ORB. First (according to the documentation), you must set up naming services. You do this by setting some registry entries on each box from which you’re going to run CORBA clients.
After setting up the naming services, I tried building the sample programs. Unfortunately, the build didn’t work. Turns out that I had built the ORB in “debug” mode (usually a pretty good idea, especially when testing new code). However, that adds a “d” to the end of each built library module (as in “omnithread_rtd.lib”—notice the final “d”). A quick change to the makefiles in each of the sample directories fixed that problem. (The problem is documented inside each .mak file, but must be fixed in each .mak file separately.)
I then tried to run the example programs. The first example (“echo”) comes in three flavors: Single-mode (a program that serves as both an ORB component and a CORBA client), standard-mode (an ORB component that doesn’t use CORBA Naming Services), and a name-service mode (which uses the Naming Services server, which must be running in your infrastructure). The single-mode and name-service mode programs worked fine, and the standard-mode version gave me an exception. This is probably fine, since by far the most convenient way to write CORBA apps is to use Naming Services. However, it’s not always portable to other ORBs.
The anyExample program (used only Naming Services) worked fine. The lifecycle example (used only standard-mode) gave a General Protection fault. On the bright side, all the thread test programs (multi-thread tests) worked without a glitch.
You could certainly do worse than downloading this ORB. While more complex than the Engine Room, it comes with loads of documentation (none of which I read). Also, it provides three different ways for a program to invoke services from an ORB. It gave me the impression of a fully thought-out development environment, but it will require a proper amount of study to use it most effectively.
This CORBA implementation (itself a GNU project) features a long list of impressive features. And at the price (free) you certainly can’t go very much wrong! After downloading the source from their home page (http://diamant-atm.vsb.cs.uni-frankfurt.de/~mico/), I started the build. For Windows 95/NT, it requires Visual C++. Also, the build process itself requires Windows NT.
If you build this yourself, you’ll want to read the README-WIN32 file in the top-level directory after you unzip the download package. Some important points:
1. Make sure you run the “VCVARS32.BAT” script file in the Visual C++ bin directory.
2. Edit the file MakeVars.win32 and change the SRCDIR variable to point to the directory where you unzipped the download package (defaults to “J:\mico”—probably not what you want!).
3. The readme file gives two ways of building the application (one for NT and one for 98). However, in the top paragraph they specifically state that the build “probably” won’t work under 98 unless you buy their book. I didn’t buy their book!
4. The readme file lists several bugs with Windows—the author doesn’t seem very happy with Visual C++! He strongly recommends that you use Visual C++ 6.0 (all the time, not just for building the MICO package), since they ran into so many problems when using version 5.0.
To run any MICO application under Windows/95, you’ll need Winsock2. You can get this from http://www.microsoft.com/windows95/downloads/contents/wuadmintools/s_wunetworkingtools/w95sockets2/default.asp?site=95. (Alternatively, you can download Winsock2 from http://www.webattack.com/download/dlwinsock2.shtml.)
I was a little disappointed to read that many of the samples don’t work under Windows (the readme file didn’t mention which ones). Also, the authors mentioned an intermittent program crash that may require programmers to statically link the files typecode.obj and util.obj with their application. My advice: always link with these files! Why take the chance?? (For those that need to know, the two files are located under <install-dir>/win32-bin/lib.) However, don’t necessarily be put off by these problems. Since all applications have bugs, it’s better to know as much about them up-front as possible. In fact, one could argue that MICO’s willingness to acknowledge its bugs is a big plus.
Sadly, the build process failed (on the last module, as it turned out). I tracked the problem down to a bum line in the “coss/trader/Makefile.win32” file. You’ll need to replace the line:
$(LINK) $(LDFLAGS) $(SRV_OBJS) $(LDLIBS) /out:traderd.exe
$(LINK) $(LDFLAGS) $(SHARED_LIB_OBJS) $(SRV_OBJS) $(LDLIBS) /out:traderd.exe
(Note the “$(SHARED_LIB_OBJS)”)
After fixing this problem, the build process (for the ORB itself) worked fine. Then, I tried building the demo projects under the “demo” directory. (To build these projects, I had to add <install-dir>/win32-bin to my system path.) The build process worked well (except for the “trader” demo—which happened to be the same library that wouldn’t build for the ORB!), and I started testing the demo programs. Almost all of them worked without a hitch (I didn’t even try to build/test the ones specifically testing X-Windows capability). I was most interested in the MFC demo (works with the Microsoft Foundation Classes, Microsoft’s Windows class hierarchy). It worked perfectly, and the source code was easy to follow.
In spite of the problems associated with building this ORB, I’m still impressed with it. The many demo programs show that a developer can approach common problems from different directions. And the fact that it’s a GNU project ensures that documentation and ongoing development are sure to continue.
I’m literally running out of space for these ORBs (in this article and on my machines), and I haven’t even scratched the surface yet. In a future article, I’d like to compare/contrast the different ORBs we’ve looked at with a series of sample programs. The goal is to identify those ORBs that provide the best portability with the least amount of effort. Unfortunately, that’s for another day.
In my last column, I said I’d develop my own Telnet server. And I have written part of a Java Telnet server. It was interesting to read all about the Telnet protocol (a program I’ve used for years without ever bothering to understand), as well as trying to implement the required functionality in the Java language.
Basically, the main problem with using Java is in properly sending/receiving command output. I started by addressing both NT and 98 as my preferred platforms. Inside my Telnet server, I wait on the configured port (23, the standard Telnet port, by default) for client connections. When a connection arrives, I spawn a new thread to handle the connection. The thread spawns a command shell to process user commands, and feeds user input to the shell. Any output from the shell is sent back to the Telnet client.
My Telnet server doesn’t support any “options” (special features that the client and the server can request each other to use)—that will come later. My biggest problem lies in handling spawned programs from the shell. For example, when I connect to my Telnet server (running on NT) I get a standard DOS command prompt. If I type a command that the command shell itself interprets (such as a DIR command), the output comes back nicely to the Telnet client. However, if I try to run a program (any text-mode program), I don’t get any output back. Strangely enough, running on 98 allows me to get output from many simple command-line programs, such as “which” or “ls”.
I suspect the problem lies within the fact that I’m using “standard input”, “standard error”, and “standard output” to retrieve information from the spawned command shell. For some reason, when the command shell itself starts a program, it isn’t returning this output to my Telnet server. I think my next tactic is to write a small C program that’s responsible for spawning/managing the command shell. This way, I have much more control over just how the command shell should handle its input and output (via the Windows CreateProcess API call, for example). For portability, I’ll try to take advantage of each supported operating system’s specific process control commands.
At worst, I’ll bypass the command shell entirely and write a simple command shell myself to interpret and execute user commands (at least for NT). It’s not as difficult as it may sound, and the goal (a fast and free Telnet server) is well worth the effort to me.
For now, you can certainly download the current effort from <editor: insert ftp address here. Put the attached ZIP package in the ftp site>. The Telnet server uses Java 1.1 (I recommend JDK 1.1.6 or higher), and should compile/run without problems under Java 1.2. Feel free to use/abuse the application as you will. If you come up with any slick solutions, I’d appreciate it if you’d drop me a line at my email address.
For the next issue, I think we’ll cover Internet TCP/IP tools. Specifically, we’ll go over the free (or almost-free) FTP clients, clock-synchronizers, communications performance enhancers, and any other cool little utilities that I can find. And, of course, your comments and interests are welcome. I’m looking forward to seeing any utilities or packages that you’ve found to be of interest. In the meantime, surf safely!