The Distributed Object Dilemma
A Technical Overview of Two Standards for Distributed Computer Systems
Brad Abrams, North Carolina State University Department of Computer Science Honors Paper.
CSC499 – Undergraduate Research Topics
Advisor: Ms. Carol Miller, Lecturer, NCSU Department of Computer Science
The nice thing about standards is, there are so many to choose from.
Organizations are moving toward a distributed computing infrastructure where a large number of computers are connected by a network. Many different kinds of workstations are located in offices and public labs are serviced by large capacity servers. Applications take advantage of this farm of computers by splitting the system into client-server partitions where the interface resides on the workstation and the application and databases reside on the servers.
Many problems arise in distributed application systems. Some of these include heterogeneous environments, network communication, authentication, information sharing, and time consistency.
One the many ramifications of living in the Post-Web revolution era is an increasingly high demand for client/server solutions. However, as the benefits of distributed solutions become clear, so do the problems. The fundamental problem facing the distributed community is the need for a common set of distributed tools with which client-server applications can be built. Two standard schemes are being touted as the "open" standard. This document describes the Distributed Computing Environment (DCE) and Common Object Request Broker Architecture (CORBA), and compares these standards.
Problem Statement
*Thesis
*Table of Contents
*Introduction
*Overview of DCE
*THE DCE ARCHITECTURE
*Distributed File Service
*Time Service
*Directory Service
*Security
*Threads
*Remote Procedure Call (RPC)
*Evolution
*Summary
*Overview of CORBA
*THE CORBA ARCHITECTURE
*Object Request Broker
*Client
*Object Implementation
*Dynamic Invocation
*IDL Stubs and Static IDL Skeletons
*Dynamic Skeleton
*ORB Interface
*Making A Request
*Evolution
*Summary
*Comparison of DCE and CORBA
*Overview
*On Being Object-Oriented
*Pure OO
*Practical OO
*In The Code
*The Industry Players
*Future Directions
*Summary
*Appendix A Sample CORBA Code
*Chapter 2 PowerBroker CORBAplus Quick Start
*2 .0 Setting Up Your Environment
*2 .1 Hello World!
*2 .2 Using Visual C++ 4.0
*2 .3 The Interface
*2 .4 Implementing the Interface
*2 .5 The Applications
*2 .6 Running the Applications
*2 .7 Build Notes
*Appendix B Sample DCE Code
*client.c
*server.c
*arithmetic.idl
*win.h (PC-DCE specific definitions)
*Bibliography
*Introduction
The Open Software Foundation (OSF) Distributed Computing Environment (DCE) and Object Management Group (OMG) Common Object Request Broker Architecture (CORBA) are often seen as competing technologies. Both support the creation and integration of client-server applications in heterogeneous distributed environments.[8] Both standards are partially based on a relatively old concept of remote procedure calls. These standards attempt to hide the underlying complexity of dealing with networked computing by providing the application developer a set of APIs (in the case DCE) or Objects (in the case of CORBA). Ideally, these interfaces allow developers to write distributed applications in the same way conventional applications are developed.
Figure 1 is a high level depiction of the way in which service requests are handled by DCE and CORBA. Both of these standards define their own Interface Definition Language (IDL) which is used to generate the code that hides the underlying complexity of distributed computing. The DCE IDL is based on the C programming language and the CORBA IDL is based on C’s Object-Oriented counterpart, C++. Specifically the IDL is used to define the set of services that a client may request from a server. Both the DCE IDL and the CORBA IDL are compiled into the client and server stubs. A client application calls a client stub to request a service. The client stub interfaces to the runtime system (perhaps, over a network), which eventually invokes server code that implements the requested service through the appropriate server stub.[8]

With both DCE and CORBA, distributed applications do not need to be concerned with traditional network problems. These problems include: where clients and servers are located on the network and differences between hardware platforms, operating systems, implementation languages, networking protocols, and others. [8] Although DCE and CORBA have the same goal, they accomplish it in different ways. As with most "standards" in the computing world, these differences make them incompatible. Applications written to the DCE standard can not interact with a server written to the CORBA standard.
We will examine both DCE and CORBA from a functional and historical background. A high level comparison of the standards and some example code are provided.
DCE is the Distributed Computing Environment, from the Open Group (formerly known as the Open Software Foundation). The OSF requests proposals for standards, accepts comments on the proposals, votes on whether to accept the standards, and then propagates them. [Microsoft]
The architecture of DCE masks the physical complexity of the networked computing environment by providing a layer of logical simplicity composed of a set of services that can be used to form a comprehensive distributed computing environment. This layer is shown between the dashed lines in figure 2. DCE provides a communications environment that allows information to flow from where it is stored (perhaps a large server) to where it is needed (perhaps a workstation in a public lab or office). This environment is designed to do this without exposing the network’s complexity to the end user, system administrator, or application developer.[3]

The above figure shows the architecture of DCE. This layered model integrates a set of fundamental technologies. The architecture is layered bottom-up from the most basic supplier of services, the operating system, to the highest-level consumers of services, applications. Security and management services are essential to all layers of the environment. To applications, DCE appears as a single logical system that can be organized into two broad categories of services: the DCE Secure Core, and DCE Data-Sharing Services.[3]
The Open Group selected Transarc’s Distributed File Service (DFS) as the standard for sharing data across its environment. DFS is designed to be a high-performance, scalable, secure method for sharing remote files. It appears to the user as a local file system, providing access to files from across the network to users anywhere on the network. In addition, DFS includes many advanced features not found in traditional distributed file systems, including caching, security, and scalability over wide-area networks. The Open Group also endorses the use of Transarc’s Enhanced File Service (EFS) to increase the availability and further simplify the administration of DFS. The Enhanced File Service delivers the ability to replicate, back up, and move different parts of the DFS file system without interruption in service to the end-user. The EFS also enables the use of Access Control Lists (ACLs) on files and directories stored in DFS, for fine-grained control over access permissions to data. The Enhanced File Service also includes a high-performance log-based physical file system for fast server restart.[3].
Controlling the order in which events are executed is a difficult problem in the distributed computing world. With processes running on many different machines across the network (each with their own, slightly different, clock) working on the same data. It is impossible to compare timestamps generated from each individual system’s clock and get a reliable measure for sequencing. In order to solve this problem, the Open Group selected the Distributed Time Service (DTS) to keep clocks closely synchronized in a distributed computing environment.
DTS synchronizes time with Coordinated Universal Time (UTC), an international time standard that is interoperable with the Internet’s Network Time Protocol (NTP). DTS enhances the dependability of a network because events occur in the correct sequence. DTS puts time stamps on applications and their procedures, which ensures operational integrity.[1]
The vast resources a distributed environment offers are beneficial only if they are easy to find. The directory services in DCE are broken down into two groups, Cell Directory Services, for communication within a close, small group of workstations and Global Directory services, for communication between these groups.
Cell Directory Service (CDS) provides the unique network addresses of named resources, such as users, servers, applications, and systems within a distributed computing environment. CDS ensures constant availability of directories and access to networked resources when they are needed. This is accomplished by way of replication of name services. Applications and users can use networked resources without concern for their physical location. [3]
Global Directory Service (GDS) provides a powerful general-purpose distributed database service that can be used for intercell communications. GDS is based on the X.500 Internet-style Domain Name Service (DNS). [3]
In a nondistributed system, the operating system can be trusted to protect resources from unauthorized access. This is not the case in a disturbed system. Communication takes place over an accessible network, where messages between machines can be observed, tampered with or forged. Security is build into the DCE specification in order to prevent these types of problems. DCE Security provides secure communications and controlled access to resources in a distributed system using authentication, and authorization. [DCE]
Authentication verifies the identity of users and services. The DCE Authentication Service is based on MIT Project Athena’s Kerberos Network Authentication Service. The Kerberos user commands: kinit, kreset, and kdestroy are used in DCE Security. The Kerberos API is used internally by DCE Security but is not exposed directly to the application programmer. [DCE]
Once a server has verified the identity of the user who is making a request, it must determine if that user is authorized to have access to the server’s resources. This job is handled by the Privilege Server which forwards (in a secure manner) the information the server needs to know in order to grant permission to the user.[DCE]
Most modern operating systems (such as Windows NT and Solaris) and the newest generation of programming languages (such as Java) have the concept of threads built in. A thread is a basic unit of CPU utilization that is similar to what is typically thought of as a process [11]. Threads are often called "light-weight" processes because the savings they have through shared resources (such as the code segment) allow them to be cheaper to create and switch between than traditional processes. Threads are particularly important in the distributed world because so much time is spent waiting for messages from across the network. This is particularly true in the case of RPCs. While one thread is blocked on a RPC, another thread can be easily switched in to get some additional work done. When the first RPC returns, that thread can be easily switched back in to complete its task.[1]
The threads package described in the DCE specification is based on POSIX 1003.4a (draft 4) that supports the creation and management of multiple threads of control within a client or server. The dispatcher that receives RPCs at a server and invokes the appropriate RPC handlers is multi-threaded which automatically permits DCE servers to handle multiple RPCs concurrently. The maximum number of concurrent RPCs at a server is easily configured by the developer, who is also responsible for ensuring the thread-safe behavior of all RPC handlers.[1]
Procedure calls are a useful and well-understood method for transferring data and control within a program on a single machine. Remote Procedure Calls extends this same mechanism to provide transfer of control and data across a network. When a remote procedure is invoked, the calling environment is suspended, the parameters are passed across the network to the environment where the procedure is to be executed, and the desired procedure is executed there. When the procedure finishes and produces its results, the results are passed back to the calling environment, where execute resumes as if returning from a simple procedure call. There are three main attractions to this method:
RPC extends the typical local procedure call model by supporting direct calls in a C-like language, called the Interface Definition Language (IDL), to procedures on remote systems. Programmers can develop distributed applications as easily as they developed traditional, single-system applications.[1]

In 1992, OSF released the first version of DCE that included all the DCE components we have described (including a reference implementation). By 1993, the first DCE implementations were available from vendors such as: AT&T, DEC, HP, IBM, SCO, SGI and Transarc[8]. Since that time, these and many other vendors have eagerly embraced each new release of DCE (DCE 1.1, 2.1.1, and 2.1.2). Microsoft appears to be betting heavily on DCE because DCE has recently been chosen as the distributed environment for DCOM, the foundation on which its ActiveX technology is built. OSF continues to evolve to support a more object-oriented paradigm for development, including support for C++ constructs in its IDL. A number of large end-user organizations have committed to basing their next-generation, enterprise-wide information systems on DCE.
DCE is a network-programming environment that attempts to hide the underlying complexity of distributed systems. It is a procedural programming environment that converts the function calls from a client to a server into RPCs. DCE takes care of all the underlying differences between the hardware (such as big endian/little endian) and the operating system (such as parameter order) through marshalling.
DCE introduces many standards into the chaotic world of distributed computing. Platform-independent implementations for threads, RPC, directory services, time services, security, and data sharing are all detailed in DCE.
CORBA (Common Object Request Broker Architecture) is a standard for distributed objects being developed by the Object Management Group (OMG). Founded in 1989, the Object Management Group, Inc is an international organization supported by over 500 members, including information system vendors, software developers and users. The organization’s primary goals are the reusability, portability, and interoperability of object-based software in distributed, heterogeneous environments. In order to meet these goals, OMG is developing CORBA and its related technologies. [4]
CORBA provides the mechanisms by which objects transparently make requests and receive responses. The CORBA provides an application framework that makes it possible for the different components of a distributed solution (known as "objects" in the CORBA world) to be built using different languages, and run on different machines in a heterogeneous environment.
The Reference Model describes the components that make up CORBA. This model consists of the following components: Object Request Broker, Object Services, Common Facilities, and Application Objects. Although this discussion will focus primarily on the Object Request Broker, its important to understanding how it fits into the structure of the CORBA architecture.
Object Request Broker (ORB) enables objects to make and receive requests and responses in a distributed environment without regard to network issues. It is the foundation for building applications from distributed objects. The ORB provides the capability for interoperability between applications in heterogeneous environments. We will focus on the architecture of this component in the following discussion. [4]
The Object Services are a collection of services (interfaces and objects) that support basic functions for using and implementing objects. Services are necessary to construct any distributed application and are always independent of application domains. For example, the Life Cycle Service defines conventions for creating, deleting, copying, and moving objects. The service does not dictate how the objects are implemented in an application. [4]
The Common Facilities are a collection of services that many applications may share, but which are not as fundamental as the Object Services. For instance, a system management or electronic mail facility could be classified as a common facility. [4]
Application Objects are typically products of a single vendor or in-house development group that controls their interfaces. Application Objects correspond to the traditional notion of applications, so they are not standardized by OMG. Instead, Application Objects constitute the uppermost layer of the Reference Model. [4]
The Object Request Broker is the core of the Reference Model. It provides the basic mechanism for making and receiving requests. Combined with the Object Services, it ensures meaningful communication between CORBA-compliant applications. The ORB most closely relates to the features of DCE we discussed above. We will focus mainly on the ORB in this discussion. [4]
The entity that wishes to perform an operation on an object is called the client. The code and data that actually implements the object is called the Object Implementation. The Object Request Broker (ORB) is responsible for all of the mechanisms required to find the object implementation for the request, to prepare the object implementation to receive the request, and to communicate the data making up the request. The interface to the object the client sees is completely independent of where the object is located, what programming language it is implemented in, or any other aspect which is not reflected in the object’s interface. [4]

Figure 4 shows the structure of an individual ORB. The interfaces to the ORB are shown by narrow boxes, and the arrows indicate whether the ORB is called or performs an up-call across the interface.
The client invokes an operation on an object implementation. Using the services of a remote object should be transparent to the caller. The goal is to have this be as simple as calling a method on an object. The remaining components discussed help to support this level of transparency. [6]
Object Implementations define the operations that implement a CORBA IDL interface. Object implementations can be written in a variety of languages including C, C++, Java, Smalltalk, and Ada. [6]
The Dynamic Invocation Interface (DII) allows a client to directly access the underlying request mechanisms provided by an ORB. Applications use the DII to dynamically issue requests to objects without requiring IDL interface-specific stubs to be linked in. Unlike IDL stubs (which only allow RPC-style requests), the DII also allows clients to make non-blocking deferred synchronous (separate send and receive operations) and one-way (send-only) calls. [6]
IDL Stubs and Static IDL Skeletons
CORBA IDL stubs and skeletons serve as the glue between the client and server applications, and the ORB. The transformation between the IDL definitions and the target programming language are automated by an IDL compiler. The use of a compiler reduces the potential for inconsistencies between client stubs and server skeletons and increases opportunities for automated compiler optimizations. [6]
The Dynamic Skeleton Interface (DSI) is the server side’s analogue to the client side’s DII. The DSI allows an ORB to deliver requests to an object implementation that does not have compile-time knowledge of the type of the object that it is implementing. The client making the request has no idea whether the implementation is using the type-specific IDL skeletons or the dynamic skeletons. [6]
An ORB is a logical entity that may be implemented in various ways. To decouple applications from implementation details, the CORBA specification defines an abstract interface for an ORB. This interface provides various helper functions such as converting object references to strings and vice versa. The ORB Interface also provides function for creating argument lists for requests made through the dynamic invocation interface (DIII). [6]
To make a request, the Client can use the Dynamic Invocation Interface or an OMG IDL stub. The Client can also directly interact with the ORB for some functions. [4]
The Object Implementation receives a request as an up-call either through the OMG IDL generated skeleton or through a dynamic skeleton. The Object Implementation may call the Object Adapter and the ORB while processing a request. Definitions of these interfaces are defined in two ways. Interfaces can be defined statically in CORBA’s C++ based interface definition language, called the OMG IDL. This language defines the types of objects according to the operations that may be performed on them. The parameters to those operations are also defined in the IDL. Interfaces can also be added to an Interface Repository service. This service represents the components of an interface as objects. This representation permits run-time access to these components. The Interface Definition Language and the Interface Repository have the ability to express the same information. [4]
A client can perform an operation by having access to an Object Reference for an object and knowing the type of the object. The client initiates the requests by calling stub routines that are specific to the object or by constructing the request dynamically. The dynamic and stub interfaces for invoking a request gather the same information from the client. The receiver of the message cannot know whether a stub or dynamic interface was used in the call. [4]
The ORB’s job is to locate the appropriate implementation code, transmit the parameters and transfer control to the Object Implementation. The transfer of control is done through an IDL skeleton or a dynamic skeleton. Skeletons are specific to the interface and the object adapter. In performing the request, the object implementation may obtain some services from the ORB through the Object Adapter. When the request is complete, the ORB passes control and output values back to the client. [4]
OMG adopted the CORBA 1.0 specification in late 1991. This included no CORBA Services or CORBA Facilities, nor did OMG release a reference implementation. By mid-1993, the first CORBA-conformant ORBs were available. By late 1993, the first CORBA Services were specified by OMG. A partial list of vendors who are currently selling or developing CORBA-conformant ORBs includes: DEC, Expersoft, HP, IBM, Technologies, Postmodern Computing, JavaSoft and SunSoft.[8]
At this time, OMG has specified few of the CORBA Services and Facilities in its specification. Furthermore, few of the specified implementations of the CORBA Services are available yet. Nonetheless, several large end-user organizations are prototyping elements of their next-generation, enterprise-wide information systems using CORBA.[8]
CORBA is an object model for distributed computing that attempts to encapsulate the complexity of distributed computing. CORBA provides an architecture independent mechanism for object interaction across a heterogeneous environment. CORBA leaves to its implementers the underlying details of exactly how architecture dependant issues are solved. As we will see later in this paper, CORBA is often implemented on top of DCE.
Clearly, DCE and CORBA attempt to solve the same kinds of problems that arise in a distributed computing environment. In general, DCE is implemented at a lower level than CORBA. In fact, CORBA is often implemented on top of a DCE layer. Things such as the file system, and security are defined explicitly in DCE (DFS and Kerberos, respectively). CORBA merely defines an interface into which the file system and security fit.
The overall distinction between CORBA and DCE is that CORBA is designed to be object-oriented and DCE is designed to support procedural programming. CORBA supports all the usual properties of Object Oriented Programming Environments: Encapsulation, Abstraction, Inheritance, and Polymorphism, as well as many other common features found in object-oriented environments. DCE, as in many distributed procedural programming environments, does not use an object-oriented model. DCE’s basic model is to partition the program’s data and the functions that manipulate the data into servers and then distribute these servers across multiple hosts and change function calls to RPCs as appropriate. [8]
Although DCE is not designed to be object-oriented, it includes a large fraction of what is required to qualify as object-oriented. First, a DCE server can be thought of as a grouping together of data and methods (called remote procedures). This is somewhat object-like, although perhaps on a larger scale than the average object. [10]
Second, DCE already supports encapsulation and polymorphism, two of the required characteristics for object-orientation described above. Encapsulation in DCE can be seen through how DCE defines the relationship between a client and server. In DCE, the developer must specify that relationship through DCE’s Interface Definition Language (IDL). An IDL interface explicitly spells out the remote procedures that the client can invoke in the server. Since the only way a client can access the server’s data is through these procedures, the server’s data is effectively encapsulated. [10]
DCE also supports polymorphism. A DCE server can allow two or more different sets of remote procedure implementations to be accessed through the same interface. A client identifies which of these implementations it wishes to invoke (i.e., which of the object’s methods it wishes to execute) by specifying a universal unique identifier (UUID) for a particular object. To the client, each of these objects presents the same interface, but in fact, the "methods" in those objects may well be implemented differently. This is polymorphism, and it was built into DCE by its original designers. [10]
Encapsulation and polymorphism are present in DCE today, but there is no support for inheritance of any kind. A large fraction of what is required for something to be considered object-oriented is already built into DCE. This suggests that modifying DCE to directly support objects should not be an impossible task. [10]
To many developers, the requirement for being object-oriented is the ability to write code in an object-oriented language such as C++. As long as the standard interface to DCE is defined only in C, DCE can never be seen as truly object-oriented. This a good point, just as one could use C or even assembly language to develop object-oriented applications, it is much easier and far more natural to do it in an object-oriented language, such as C++. To meet this need, several different attempts have been made to define object-oriented add-ons to DCE, usually in the form of C++ class libraries. The most widely used of these is a Hewlett Packard product called OODCE [Chappel].
These features of DCE provide support for object-oriented programming even though DCE is still a procedural environment. This is very similar to the way in which the C programming language is used to implement C++ (such as in C-Front compilers). In fact, many prominent CORBA compliant ORB vendors are implementing ORBs on top of DCE.
One of the main goals for both DCE and CORBA is to hide the underlying complexity of dealing with a network and generally make development and support of networked software easier. It is difficult to see from specifications how well DCE has met this goal, therefore some sample code for using CORBA has been included in Appendix A and some sample code using DCE has been included in Appendix B.
Microsoft seems to be leading the DCE camp with its version of the standard built into Distributed COM (the basis for its ActiveX technology for distributed computing). Sun’s Java and Netscape’s Netscape One, seem to be the big players behind CORBA. These big players are pushing for rapid development within each standard making it very unclear which will come out on top. Although DCE and CORBA are not inherently competitive, their corporate backers are.
This competition is very easy to see this in the web-browser market. Microsoft’s Internet Explorer contains technology to build web-based applications with its DCE based ActiveX technology, whereas Netscape’s browsers allows web-based applications to be build using its CORBA based Netscape One technology. Microsoft has no plans to support Netscape ONE in future releases of Internet Explorer. Likewise, Netscape has not announced any plans to support ActiveX, although it is being pressured by some of its corporate customers to support the standard.
Both Netscape and Microsoft have full support for Sun’s Java architecture (the JavaVM) which allows web-based developers a browser-neutral development package. However, Microsoft’s implementation of the JavaVM allows developers to use ActiveX (DCE) in addition to CORBA. Of course, Netscape has no plans to make the same additions to its JavaVM. If a developer chooses to make use of the ActiveX capabilities (with which a large portion of the current web-developers are already comfortable) in Microsoft’s browsers their application will not work on Netscape’s.
In the fast paced computer industry, it is very difficult to determine which standards will become dominate. Both DCE and CORBA have many large industry players pouring resources into new updates.
The latest release available for DCE, DCE 1.2.2, includes an enhanced version of the IDL that supports C++ constructs and a number of object-oriented features. The inspiration for many of these new features came from CORBA and ActiveX. These new features include the ability to pass references to objects as parameters, interface inheritance, and support for the generation of C++ header files. With the latest release, DCE is making an effort to easily integrate with other computing environments, such as Novell’s Netware 3.x. Security and Distributed File System support continues to play an important role in DCE’s evolution.
At this time, many of the features of the CORBA 2.0 specification have not been fully implemented. This implementation is an ongoing process by many CORBA vendors. Growing interest in CORBA is due to the fact that many of the fastest growing network technologies make use of CORBA. CORBA’s Interface Definition Language (IDL) is on track to become an ISO Standard this year. Becoming an international standard will only help OMG IDL be propagated more quickly and to more different areas. [OMG97]
CORBA and DCE attempt to solve the same types of problems that arise in a distributed computing environment. CORBA was designed to solve these problems in an Object-Oriented way, whereas DCE was designed to be procedural. However, many tools exist to encapsulate DCE in an Object Oriented way. Microsoft seems to be leading the DCE camp with its version of the standard built into Distributed COM (the basis for it much touted ActiveX technology for distributed computing). Sun’s Java and Netscape’s Netscape One, seem to be the big players behind CORBA. These big players are pushing for rapid development within each standard making it very unclear which will come out on top.
The following information has been made available in an effort to help the reader understand the realties of developing with the CORBA specification. Expersoft’s CORBAplus is a comprehensive implementation of the Object Management Group's CORBA 2.0 specification. The following is an expert from the documentation available on using CORBAplus. More information can be found at:
http://www.expersoft.com/prod_ser/index.htm.

Use the following Quick Start tutorial to get up and running with PowerBroker CORBAplus.
Before you begin, verify that PowerBroker has been correctly installed on your system. Refer to the installation instructions that accompany this product for complete installation instructions.
Also, verify that you have added the PowerBroker bin directory to your system's path statement. See the instructions in the preceding chapter for details.
This tutorial demonstrates how easy it is to create a distributed application using PowerBroker, Following the instructions, you will:
The source code and project files used in this tutorial are available in the %PBHOME%\examples\corba\hello directory. You may prefer to compile the tutorial applications from this directory to save on typing. However, building Visual C++ project files for PowerBroker applications is a useful exercise, so at the very least you should study the provided project files carefully.
To use this example with Microsoft Visual C++ or later, follow the steps below to set up a project workspace.
Select File = New from the menu, then select
Project Workspace.
Specify the following:
Type: Static Library
Name hellolib
Location getstart
2.3.1 To create the IDL interface:
interface GreetingServer
{
string greeting();
};
2.3.2 Run the IDL compiler to generate C++ code from the IDL file.
The IDL compiler can be run as a character-based application from the MS-DOS command line, or as a graphical application from Windows NT.
To run the IDL compiler as a character-based application:
2.3.2 To run the IDL compiler as a graphical application:
NOTE: The PowerBroker bin directory must be in your path in order for the graphical interface to work properly.
The IDL compiler generates four C++ files from the original hello.idl interface:
hello.h hello.C hello_s.h hello_s.C.
hello.h and hello.C define and implement client stubs, utility classes, and C++ implementations of CORBA types; basically everything necessary to get a CORBA client application running. hello_s.h and hello_s.C define and implement server implementation details; hence the _s for server.
After the IDL source is successfully compiled, write the code to implement the interface functionality. Then, compile the implementation and the IDL generated code into a library for linking into your applications. You may also copy the files from the examples\hello subdirectory in the PowerBroker installation directory.
#include <hello_s.h
class GreetingServer_impl
:
virtual public GreetingServer_base_impl
{
public:
virtual CORBA::String greeting();
};
#include <hello_i.h
CORBA::String
GreetingServer_impl::greeting()
{
/* It is the responsibility of the caller to release
memory allocated by the following CORBA_string_dup.
See the User's Manual for an explanation. */
return CORBA_string_dup("Hello World!");
}
For example, if the project file is in the same directory as the source code, and you installed
PowerBroker to c:\pbcp, add ..., c:\pbroker\include. For more information, see Build Notes at the end of this chapter.
NOTE: If you have added the PowerBroker include directory to the list of standard include paths for Visual C++, you do not have to add it to your project settings. See the installation chapter for details.
Select Insert = Files Into Project. Open the getstart\hellolib directory. Select all the files, then click OK.
To see the interface in action, build a server application that instantiates the new implementation and a client application that connects to the server and makes a request on it.
#include "hello_i.h"
#include <pbroker/winsvc/winsvc.h
#include <pbroker/corba/orb.h
#include <pbroker/corba/xpsboa.h
int
main(int argc, char **argv)
{
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_ptr aboa = CORBA_BOA::_nil();
XpsBOA * pboa = XpsBOA::_nil();
XpsEventService eventService;
if (!CORBA::is_nil(orb))
{
aboa = orb-BOA_init(argc, argv);
pboa = XpsBOA::_narrow(aboa);
// the next try block simply initializes the QuoteServer
try
{
if (!CORBA::is_nil(pboa))
{
GreetingServer_ptr gs = new GreetingServer_impl; // create instance
// register instance
pboa-obj_is_ready(gs, nil);
// register alias for instance to use URLs with initialization
// service
pboa-registerAlias(gs, "HelloServer"); //
}
}
catch (CORBA::Exception & exc)
{
cout << "\nGreetingServer: Caught exception (" <<
exc._repository_id() << ")\n" << endl;
}
// finally, we process application events
eventService.mainloop(); // control will not return to this point
}
else
{
cout << "\nGreetingServer: Error initializing ORB.\n" << endl;
}
return 0;
}
#include <pbroker/winsvc/winsvc.h
#include <pbroker/corba/orb.h
#include <hello_i.h
int
main (int argc, char** argv)
{
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
/*
The following try block attempts to obtain a reference
to an existing HelloServer object by name through the
initialization service. The HelloServer object must
already exist in a running HelloServer application
process, and the object reference must be available in
this client's process.
The name resolution takes place via the CORBA initialization
service. During ORB_init() the ORB obtains initial object
references from the command line and the shell environment.
After ORB_init() initial references may be obtained by name.
After the HelloServer reference is obtained, the client makes
a call on the r emote greeting function, outputs its result,
then exits.
If the name resolution fails, then the client exits.
*/
try
{
if (!CORBA::is_nil(orb))
{
CORBA::Object_var obj = orb-resolve_initial_references(
"HelloServerRef");
if (!CORBA::is_nil(obj))
{
GreetingServer_ptr gs_ptr = GreetingServer::_narrow(obj);
if (!CORBA::is_nil(gs_ptr))
{
CORBA::String_var returned;
returned = gs_ptr-greeting();
cout <<<< endl;
CORBA::release(gs_ptr);
return 1;
}
}
CORBA::release(orb);
}
}
catch(CORBA::Exception & exc)
{
cout << "\nHelloClient: Caught exception (" << exc._repository_id()
<< ")\n" << endl;
}
return 0;
}
To run the applications:
hellocli -pbinit HelloServerRef [server_URL] / HelloServer
The URL takes the following form:
iiop://:
For example, if host satori has a server listening at port 7777,
use the command:
hellocli -pbinit HelloServerRef iiop://satori:7777/HelloServer
The client connects to the server and calls the distributed greeting operation. The server returns the string "Hello World!", and the client proudly displays this return value to the screen. To verify that the client is indeed connecting to the server, you can specify the -pbtrace flag on the client's command line.
Follow the suggestions below to create make/project files that include PowerBroker components.
Section Parameter Setting Code Gen Processor 80386 RTL Multithreaded DLL Call Conv __cdecl Struct Mem 8 Bytes
This sample application was ported with approval from "O'Reilly & Associates, Inc." as part of an agreement with Gradient Technologies to bring the sample programs detailed in the "Guide to Writing DCE Applications" to the PC-DCE environment. This and all the other samples available are fully detailed within that publication. There are intentionally no changes in functionality with the port to windows, and with the Arithmetic Client application here, a simple Windows modeless dialog box is used to initiate and terminate the program. All output and returns from the server are logged to a scrollable box within the new window.
/*
* Copyright Gradient Technologies, Inc. (1991, 1992, 1993, 1994, 1995)
*/
/* FILE NAME: client.c */
/* This is the client module of the arithmetic example. */
#include <stdio.h>
#include <windows.h>
#include <dce/rpc.h>
#include "win.h" /* includes PC-DCE specific info */
#include "arith.h" /* header file created by IDL compiler */
long_array a ={100,200,345,23,67,65,0,0,0,0};
long_array b ={4,0,2,3,1,7,5,9,6,8};
/*
main () * not used with windows *
* have changed the entry *
* point to be the new *
* SendToServer() */
int SendToServer()
{
long_array result;
int i;
printf("entering the RPC");
sum_arrays(a, b, result); /* A Remote Procedure Call */
printf("sums:");
for(i = 0; i < ARRAY_SIZE; i++)
printf("%ld\n", result[i]);
printf(" ..Press CALL to run again");
BackgroundThread = FALSE; /* reset the RPC active *
* flag to prevent re- *
* entrancy with the DLL */
return 0;
}
/* FILE NAME: server.c */
#include <windows.h> /* part of windows port */
#include <dce/rpc.h> /* part of windows port */
#include "win.h" /* part of windows port
#include <stdio.h> not needed with windows*/
#include "arith.h" /* header created by the idl compiler */
//#include "chk_stat.h" /* header with the ERROR_CHECK macro */
/*
main () * not used with windows port, instead *
* we enter this module from the new *
* "clientw.c", and call to ServerListen*/
int ServerListen(char *server_name)
{
unsigned32 status; /* error status (nbase.h) */
rpc_binding_vector_t *binding_vector; /* set of binding
handles(rpcbase.h)*/
unsigned_char_t *entry_name; /*entry name for name service
(lbase.h)*/
char *getenv();
printf("Registering server interface...\n"); /* added for
windows */
printf("");
rpc_server_register_if( /* register interface with the RPC
runtime */
arithmetic_v0_0_s_ifspec, /* interface specification
(arithmetic.h) */
NULL,
NULL,
&status /* error status */
);
ERROR_CHECK(status, "Can't register interface\n");
rpc_server_use_all_protseqs( /* create binding information */
rpc_c_protseq_max_reqs_default, /* queue size for calls
(rpcbase.h) */
&status
);
ERROR_CHECK(status, "Can't create binding information\n");
rpc_server_inq_bindings( /* obtain this server's binding
information */
&binding_vector,
&status
);
ERROR_CHECK(status, "Can't get binding information\n");
rpc_ns_binding_export( /* export entry to name service database */
rpc_c_ns_syntax_default, /* syntax of the entry name
(rpcbase.h) */
(unsigned_char_p_t) server_name, /* entry name for name
service */
arithmetic_v0_0_s_ifspec, /* interface specification
(arithmetic.h)*/
binding_vector, /* the set of server binding
handles */
NULL,
&status
);
ERROR_CHECK(status, "Can't export to name service database\n");
rpc_ep_register( /* register endpoints in local
endpoint map */
arithmetic_v0_0_s_ifspec, /* interface specification
(arithmetic.h) */
binding_vector, /* the set of server binding
handles */
NULL,
NULL,
&status
);
ERROR_CHECK(status, "Can't add address to the endpoint map\n");
rpc_binding_vector_free( /* free set of server binding
handles */
&binding_vector,
&status
);
printf("Status:");
printf("Listening for remote procedure calls...");
ERROR_CHECK(status, "Can't free binding handles and vector\n");
rpc_server_listen( /* listen for remote calls */
rpc_c_listen_max_calls_default, /*concurrent calls to server
(rpcbase.h)*/
&status
);
printf("rpc_server_listen() failed...");
ERROR_CHECK(status, "rpc listen failed\n");
EndDialog (hwndArithDlg,0);
PostMessage (hwnd, WM_DESTROY, 0 ,0);
}
/* FILE NAME: arithmetic.idl */
/* This Interface Definition Language file represents a basic arithmetic */
/* procedure that a remote procedure call application can use. */
[
uuid(C985A380-255B-11C9-A50B-08002B0ECEF1)
] /* Universal Unique ID */
interface arithmetic /* interface name is arithmetic */
{
/* an unsigned integer constant */
const unsigned short ARRAY_SIZE = 10;
/* an array type of long integers */
typedef long long_array[ARRAY_SIZE];
/* The sum_arrays procedure does not return a value */
void sum_arrays (
[in] long_array a, /* 1st parameter is passed in */
[in] long_array b, /* 2nd parameter is passed in */
[out] long_array c /* 3rd parameter is passed out */
);
}
win.h (PC-DCE specific definitions)
/*
* win.h
*
* Definitions used by the "arithmetic" application
*/
/*
* Macros
*/
#define MAX_STR 128
/*
* Define MSC 7.0 windows.h macros and typedefs if using MSC 6.0.
*/
#if (_MSC_VER <= 600)
#define HINSTANCE HANDLE
#define WINAPI _far _pascal
#define CALLBACK _far _pascal
typedef unsigned int UINT;
typedef UINT WPARAM;
typedef LONG LPARAM;
typedef LONG LRESULT;
#endif
/*
* Global variables
*/
extern HWND hwnd;
extern BOOL BackgroundThread;
extern char AppName[];
extern HWND hwndArithDlg;
extern int OutLines;
/*
* Global functions
*/
extern int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int);
extern BOOL InitApplication (HANDLE);
extern BOOL InitInstance (HANDLE, int);
extern long WINAPI MainWndProc (HWND, unsigned, WPARAM, LPARAM);
extern BOOL CALLBACK ArithDlgProc (HWND, UINT, WPARAM, LPARAM);
extern int SendToServer ();
extern int ServerListen (LPSTR);
/* Used for util.c
*/
#define ERROR_CHECK(status, text) \
if (status != error_status_ok) error_exit (status, text)
extern void error_exit (error_status_t, LPSTR);
extern void MsgBox (LPSTR msg);
extern int printf (const char *, ...);
(C) Copyright Gradient Technologies, Inc.. 1994. All rights reserved.
Arithmetic Sample Application for PC-DCE
Transactions on Computer Systems, Vol.2 No. 1, February 1984, Pages 39-59.