Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

245e573e69512b6b24717a412f7822265c2172772d577d303927537d5e715c5757

70784a2734385832694f3e7433483753276f4825305a2858382e4a30667577487b

3647343e3e7e5b554b21643d67613c6d367a4e784d414f7a7658606d214a45677e

272f737756642420000000000000

3.4 Writing and Compiling a Client

The source code for the client also takes only a few lines of code:

#include <iostream.h> #include <iomanip.h> #include "time.hh"

int

main(int argc, char * argv[])

{

try {

//Check arguments if (argc != 2) {

cerr < "Usage: client IOR_string" < endl; throw 0;

}

//Initialize orb

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

// Destringify argv[1]

CORBA::Object_var obj = orb->string_to_object(argv[1]); if (CORBA::is_nil(obj)) {

cerr < "Nil Time reference" < endl; throw 0;

}

// Narrow

Time_var tm = Time::_narrow(obj); if (CORBA::is_nil(tm)) {

cerr < "Argument is not a Time reference" < endl; throw 0;

}

// Get time

TimeOfDay tod = tm->get_gmt(); cout < "Time in Greenwich is "

<setw(2) < setfill('0') < tod.hour < ":"

<setw(2) < setfill('0') < tod.minute < ":"

<setw(2) < setfill('0') < tod.second < endl;

}

catch (const CORBA::Exception &) {

cerr < "Uncaught CORBA exception" < endl; return 1;

}

catch (...) { return 1;

}

return 0;

}

53

IT-SC book: Advanced CORBA® Programming with C++

We must include the client-side available to the client application initializes the ORB run time with

header file, time.hh, to make the IDL definitions code. The code then does a simple argument check and

ORB_init:

#include <iostream.h> #include <iomanip.h> #include "time.hh"

int

main(int argc, char * argv[])

{

try {

// Check arguments if (argc != 2) {

cerr < "Usage: client IOR_string" < endl; throw 0;

}

// Initialize orb

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

Note that we throw zero to implement a simple form of error handling. An exception handler at the end of main ensures that the client exits with non-zero status if anything goes wrong.

The next few lines convert the command-line argument, which is expected to be a stringified reference to a Time object, back into an object reference:

// Destringify argv[1]

CORBA::Object_var obj = orb->string_to_object(argv[1]); if (CORBA::is_nil(obj)) {

cerr < "Nil Time reference" < endl; throw 0;

}

This results in a reference to an object of type Object. However, before the client can invoke an operation via the reference, it must down-cast the reference to the correct type, namely Time:

// Narrow

Time_var tm = Time::_narrow(obj); if (CORBA::is_nil(tm)) {

cerr < "Argument is not a Time reference" < endl; throw 0;

}

The call to Time::_narrow has the same purpose as a C++ dynamic cast: it tests whether a reference is of the specified type. If the reference has the specified type, _narrow returns a non-nil reference and nil otherwise.

54

IT-SC book: Advanced CORBA® Programming with C++

The client now holds an active object reference to the Time object in the server and can use that object reference to obtain the current time:

// Get time

TimeOfDay tod = tm->get_gmt(); cout < "Time in Greenwich is "

<setw(2) < setfill('0') < tod.hour < ":"

<setw(2) < setfill('0') < tod.minute < ":"

<setw(2) < setfill('0') < tod.second < endl;

The call to get_gmt invokes a remote procedure call to the get_gmt method in the server. The call blocks until the current time is returned by the server; the client prints the result on stdout. Note that this will work no matter where the server is located. The ORB transparently takes care of locating the Time object and dispatching the request to it.

The remainder of the client consists of two exception handlers that implement simple error handling. (The closing curly brace at the start of this code fragment completes the try block we opened at the beginning of main.)

}

catch (const CORBA::Exception &) {

cerr < "Uncaught CORBA exception" < endl; return 1;

}

catch (...) { return 1;

}

return 0;

}

Again, how to compile the client depends on your compiler and ORB. The main point is that we must compile both the generated stub code (timeC.cc) and our client application code, which we assume is in the file myclient.cc. The link line also depends on your compiler and ORB. We assume here that both client and server use the same ORB run-time library:

$ CC -c -I/opt/myORB/include timeC.cc

$ CC -c -I/opt/myORB/include myclient.cc

$ CC -o myclient timeC.o myclient.o -L/opt/myORB/lib -lorb

Assuming that there are no errors, this results in a client executable called myclient.

3.5 Running Client and Server

To run our application, we must first start the server. We redirect the object reference string printed by the server into a file so that we can easily pass it on the command line

55

IT-SC book: Advanced CORBA® Programming with C++

for the client. To retain use of the terminal while the server is running, we run the server in the background.

After the server is running, we start the client, passing it the object reference printed by the server on the command line. The client reads the current time via the passed reference and prints the time on stdout before it exits again. Finally, we terminate the server by sending it a SIGTERM:

$ ./myserver >/tmp/myserver.ref & [1] 7898

$ ./myclient `cat /tmp/myserver.ref`

Time in Greenwich is 01:35:39

 

$ kill %1

./myserver &

[1] + Terminated

$

 

3.6 Summary

This chapter presents a simple, but complete, CORBA application. As you can see, building a complete application involves four basic steps:

Step 1.

Define the IDL.

Step 2.

Compile the IDL.

Step 3.

Write and compile the server.

Step 4.

Write and compile the client.

Of course, you may be writing a client to communicate with an existing server, in which case steps 1 and 3 are unnecessary.

Looking back at the source code, you may be intimidated by the number of lines that is required for something as simple as this application. However, you need to keep in mind that most of the code in both client and server is boilerplate and seldom changes. In fact, the client really consists of only a single line that is interesting as far as the application is concerned: namely, the call to get_gmt. Similarly, the server contains only a few interesting lines: namely, the body of the get_gmt method.

Our minimal application is so small that the source code is dominated by the number of lines required to initialize the ORB run time. (In a more realistic application, that code would be encapsulated by a wrapper class.) As applications get larger, the overhead incurred by CORBA remains fixed, so almost all the code you write can concern itself with the actual application logic instead of the details of how to communicate. This is one major advantage of CORBA: it relieves you of the burden of dealing with infrastructure concerns and allows you to put your effort where you really need it—namely, toward developing the business logic of your application.

56