Different network layers provide different speeds, and sockets are the fastest. But sockets are no help when it comes to marshalling or unmarshalling user data from the plain byte buffers. Using CORBA, the marshall/unmarshall aspect of the data is taken care of outside the user application, which is very attractive.
An additional benefit of using CORBA or RMI versus sockets is the availability of a Naming Service that can be used by client applications to look up server applications. When running this example, the reader must first start the Naming Service application.
The initial step is to create an idl file with definitions for the arrays and methods for sending the arrays to the server:
typedef sequence <octet> ByteSeq;
typedef sequence <long> IntSeq;
typedef sequence <float> FloatSeq;
typedef sequence <double> DoubleSeq;
interface View {
void send_byte (in long long time, in long n, in ByteSeq
array);
void send_int (in long long time, in long n, in IntSeq
array);
void send_float (in long long time, in long n, in FloatSeq
array);
void send_double (in long long time, in long n, in DoubleSeq
array);
};
Note that the first argument in the send_xxx() methods is the system time just before the method is invoked. When running the client and the server on different systems,
the clocks must be synchronized to get accurate speed measurements.
The client gets the object reference to the server from the Naming Service and creates an instance of the ViewClient2 class which draws the menubar.
import java.awt.*;
import java.awt.event.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
public class ViewClient2 extends Frame implements ActionListener {
int i1, i2, i3;
private static View viewRef; // must be 'static'
public static void main(String args[])
{
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);
// get the root naming context
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
System.out.println("client: 1");
// resolve the Object Reference in Naming
NameComponent nc = new NameComponent("ViewServer",
"server");
NameComponent path[] = {nc};
System.out.println("client: 2");
viewRef = ViewHelper.narrow(ncRef.resolve(path));
System.out.println("client: 3");
if (viewRef==null) System.out.println("viewRef is null");
new ViewClient2 ("ViewClient2");
}
catch (Exception e) {
System.out.println("ERROR : " + e) ;
e.printStackTrace(System.out);
}
}
Next, we add the constructor to build a simple user interface. There is a simple menubar with a Choices pulldown menu. The pulldown menu "m1" is built with four menu items, with one per data type -- byte, integer, float, and double.
public ViewClient2(String title) {
super (title);
MenuBar mb = new MenuBar();
Menu m1 = new Menu("Choices");
m1.add ("send byte");
m1.add ("send integer");
m1.add ("send float");
m1.add ("send double");
m1.addActionListener(this);
mb.add(m1);
setMenuBar (mb); // Set the menu bar on the frame
setSize (350,100);
show();
}
Finally, in the callback for the menubar, we allocate an array to hold the data that's to be transferred to the server and capture the current time. The client invokes the method on the server and repeats this step with different array sizes.