Weiter | Weiter | Weiter | Weiter | Kommentar

all-inOne, section 18.

18.  Networking

18.1.  The Subject

Computer networks are the biggest Big New Thing for decades. They are now of central importance to all information technology. With the recent explosive growth of the internet, they are rapidly "she" becoming of crucial importance to all of modern society.

18.2.  A Network Architecture Example: WWW

The World Wide Web is the Big New Thing in computer networking.

History:

In 1989, Tim Berners Lee proposed a global hypertext project, to be known as the World Wide Web. Based on the earlier "Enquire" work, it was designed to allow people to work together by combining their knowledge in a web of hypertext documents. Tim Berners Lee wrote the first World Wide Web server and the first client, a wysiwyg hypertext browser/editor which ran in the NeXTStep environment. This work was started in October 1990, and the program "WorldWideWeb" was first made available within CERN in December, and on the Internet at large in the summer of 1991.

Through 1991 and 1993, Tim Berners Lee continued working on the design of the Web, coordinating feedback from users across the Internet. His initial specifications of URIs, HTTP and HTML were refined and discussed in larger circles as the Web technology spread.

See also: Tim Berners-Lee.

A browser, or viewer program is used to fetch and display "pages" of information from a server. A page is simply an ASCII text file, written using a simple markup language called Hypertext Meta Language (HTML). You may find an introduction here.

Uniform Resource Locators - URLs

The URL is the basis of the WWW. Think of a URL as an address that can lead you to any file on any machine anywhere in the world. Unlike the common postal address, however, these are written backwards. (Actually backwards makes more sense. My postal adddress was:

HP Bischof
3002 ST RT 48
Oswego, 13126 NY,
USA.

But if you want to deliver a letter to me, shouldn't you first go to the USA, then NY, then Oswego, then 3002 ST RT 48, then to HP Bischof? The URL is written in that more logical order.)

A URL defines the location of a WWW page in the following way:

service:host:port/file and resource details

For example:


http://www.cs.rit.edu:80/~hpb/CS3/all-2.2.html#section4
http://www.av.digital.com/cgi-bin/query?pg=q&what=web

URLs on the Web don't have to use the HTTP protocol. Some other URLs you might encounter are:

ftp
file transfer protocol
news
for Usenet news groups
telnet
for telnet
mailto
to send email to a specific address

Connection Establishment

To fetch a WWW page, the browser application process running on your local computer first establishes a connection to the remote host.

What this means is that the browser process uses the facilities of the network connecting the two computers to send a "connection request" message to a server process running on the computer whose name was given in the URL.

If the remote server process is prepared to accept the connection, it responds with a "connection accepted" message.

Note that we are, for the moment, ignoring the process of "looking up" the remote host - discovering the network address associated with its domain name.

The HTTP Protocol

Once the two application processes have an established connection between them, they can communicate reliably.

The browser then sends a request, in ordinary plain text, to the server, thus:

 GET /home.html

The string GET something is one of many commands defined in the Hypertext Transfer Protocol, HTTP. The server responds by returning the contents of a file.

Finally, the browser process interprets the HTML markup in the returned file, and displays it to the user.

18.3.  What is the Internet

The Internet (short for internetworking, the practice of linking technologically different and independently operated networks), is a network of networks which allows users to communicate using electronic mail, to retrieve data stored in databases, and to access distant computers. The "core" of Internet includes the National Science Foundation's NSFNET, the Department of Energy's Energy Science Network (ESnet), the NASA Science Internet (NSI) as well as Defense's ARPANET and Terrestrial Wideband Network (TWBnet). Internet also includes a larger, and continually expanding, collection of interconnected regional, campus, and other networks throughout the U.S. and overseas, as well as several networks that provide service on a for-profit basis.

These linked networks are independently operated; there is no central control of Internet. Internet began as an Advanced Research Projects Agency research project to investigate computer networking technology. The networks that comprise the National Research and Education Network (NREN), a component of the High Performance Computing and Communications Program, are a part of the current Internet.

Copied from: www.onelook.com.

18.4.  What is an Intranet

A local area network which may not be connected to the Internet, but which has some similar functions. Some organizations set up World Wide Web servers on their own internal networks so employees have access to the organization's Web document Copied from: www.onelook.com.

18.5.  Protocol

(From: An Internet Encyclopedia) Douglas Comer defines a protocol as "a formal description of message formats and the rules two or more machines must follow to exchange those messages."

Protocols usually exist in two forms. First, they exist in a textual form for humans to understand. Second, they exist as programming code for computers to understand. Both forms should ultimately specify the precise interpretation of every bit of every message exchanged across a network.

Protocols exist at every point where logical program flow crosses between hosts. In other words, we need protocols every time we want to do something on another computer. Every time we want to print something on a network printer we need protocols. Every time we want to download a file we need protocols. Every time we want to save our work on disk, we don't need protocols - unless the disk is on a network file server.

Usually multiple protocols will be in use simultaneously. For one thing, computers usually do several things at once, and often for several people at once. Therefore, most protocols support multitasking. Also, one operation can involve several protocols. For example, consider the NFS (Network File System) protocol. A write to a file is done with an NFS operation, that uses another protocol (RPC) to perform a function call on a remote host, that uses another protocol (UDP) to deliver a datagram to a port on a remote host, that uses another protocol to deliver a datagram on an Ethernet, and so on. Along the way we made need to lookup host names (using the DNS protocol), convert data to a network standard form (using the XDR protocol), find a routing path to the host (using one or many of numerous protocols) - I think you get the idea.

18.6.  Protocol Layering

Protocol layering is a common technique to simplify networking designs by dividing them into functional layers, and assigning protocols to perform each layer's task.

For example, it is common to separate the functions of data delivery and connection management into separate layers, and therefore separate protocols. Thus, one protocol is designed to perform data delivery, and another protocol, layered above the first, performs connection management. The data delivery protocol is fairly simple and knows nothing of connection management. The connection management protocol is also fairly simple, since it doesn't need to concern itself with data delivery.

Protocol layering produces simple protocols, each with a few well-defined tasks. These protocols can then be assembled into a useful whole. Individual protocols can also be removed or replaced.

The most important layered protocol designs are the Internet's original DoD model, and the OSI Seven Layer Model. The modern Internet represents a fusion of both models.

18.7.  The OSI Seven-Layer Model

(From: An Internet Encyclopedia) In the 1980s, the European-dominated International Standards Organization (ISO), began to develop its Open Systems Interconnection (OSI) networking suite. OSI has two major components: an abstract model of networking (the Basic Reference Model, or -- seven-layer model --), and a set of concrete protocols. The standard documents that describe OSI are for sale and not currently available online.

Parts of OSI have influenced Internet protocol development, but none more than the abstract model itself, documented in OSI 7498 and its various addenda. In this model, a networking system is divided into layers. Within each layer, one or more entities implement its functionality. Each entity interacts directly only with the layer immediately beneath it, and provides facilities for use by the layer above it. Protocols enable an entity in one host to interact with a corresponding entity at the same layer in a remote host.

[picture]

The seven layers of the OSI Basic Reference Model are (from bottom to top):

The original Internet protocol specifications defined a four-level model, and protocols designed around it (like TCP) have difficulty fitting neatly into the seven-layer model. Most newer designs use the seven-layer model.

18.8.  TCP/IP

TCP/IP is the essential two-layer program that each Internet point-of-presence (POP) or SLIP/PPP user must use.

The Transmission Control Protocol (a protocol is a formal set of rules for communicating) manages the packaging of data into the packets that get routed on different paths over the Internet and reassembled at their destination.

The Internet Protocol handles the address part of each data packet so that it is routed to the right destination.

TCP/IP can be used on many data-link layers (can support many network hardware implementations).

These two protocols are the most important, TCP/IP is really a suite of protocols. (Some of these are viewed as alternative protocols and others as application protocols.) The ones you are most likely to use (directly or indirectly) are: HTTP, FTP, Telnet, Gopher, PPP, and SMTP.

Related protocols, some of them may be included in a TCP/IP package:

18.9.  TCP/IP layering

TCP/IP is normally considered to be a 4 layer system:

[picture]

Link layer:
the network interface layer. Includes normally the device driver in an OS.

Network layer:
The network layer handles the movement of the packets around a network. Routing of packets takes place here. IP (Internet Protocol), ICMP (Internet Control Message Protocol), and IGMP (Internet Group Management Protocol) provide the network layer in the TCP/IP suite.
Transport Layer:
Provides a flow of data between two hosts for the application layer. There are two different protocols: TCP (Transmission Control Protocol) and UDP (User Datagram Protocol).

The function of the TCP protocol, is to provide a:

reliable              all data is delivered correctly
connection-oriented   the protocol provides procedures for establishing
                      interprocess connections.
byte stream           ie, no visible packetisation so far as the application
                      processes are concerned
end-to-end
... interprocess communication service.

The User Datagram Protocol provides a connectionless alternative transport service to TCP for applications where reliable stream service is not needed. UDP datagrams can be dropped, duplicated or delivered out of order, same as for IP.

Application Layer:
The application layer handles the details of the particalur application.

·   telnet   for remote login
·   ftp      the file transfer protocol
·   SMTP     simple mail transfer protocol
·   SNMP     simple network management protocol

An example:

[picture]

18.10.  Internet Addresses

Every Internet-connected system has a unique Internet host address.

This is a 32 bit, or 4 byte, binary number.

Internet addresses are written as a dotted sequence of the form:

a.b.c.d

where a, b, c and d etc, are the decimal values (ranging from 0 to 255) of the 4 bytes which make up the internet address, for example:

129.3.20.4

129.3.20.4 is the IP address of ilon,or to use its full name

ilon.cs.oswego.edu

We will later see how the name of a computer is mapped to its IP-address.

18.11.  IP Address Classes

[picture]

18.12.  Ethernet Address

An IP-address only makes sense to the TCP/IP suite. A data link such as an Ethernet or a token ring has its own addressing scheme (often 48 bits).

The-byte address is often used, which is divided into a 3-byte vendor ID and a 3-byte vendor-defined field. Ethernet manufacturers are assigned a unique vendor ID, and are then responsible for insuring that all of their devices have unique addresses in the last 3 bytes.

A network, such as an Ethernet can be used by different network layers at the same time. See also RFC 802.

18.13.  Encapsulation

When an application sends data using TCP is sent down the protocol stack.

A pyhsical proporty of an Ethernetframe is, that the size of its data must be between 46 and 1500 bytes.

[picture]

18.14.  TCP Ports

TCP is using protocl port numbers to indentify the ultimate destination.

How does one deteremine the port to communicate with?

--
Well known ports
--
Randomly assigned ports.

18.15.  Socket

Two popular Application Programming Interface using TCP/IP protocols are called sockets and TLI (transport layer interface).

A socket is one end-point of a two-way communication link between two programs running on the network. Socket classes are used to represent the connection between a client program and a server program. The java.net package provides two classes--Socket and ServerSocket--that implement the client side of the connection and the server side of the connection, respectively.

A socket is a network communications endpoint.

A socket is an object from which messages are sent and received.

Socket operations resemble file operations in many respects:

See also: java.net

18.16.  java.net

Through the classes in java.net, Java programs can use TCP or UDP to communicate over the Internet. The URL, URLConnection, Socket, and ServerSocket classes all use TCP to communicate over the network. The DatagramPacket, DatagramSocket, and MulticastSocket classes are for use with UDP.

18.17.  Getting Information

Host info

Src/16/HostInfo.java.minusSTART_STOP


import java.net.*;
import java.io.*;
import java.util.*;
public class HostInfo {
    public static void main(String argv[]) {
        InetAddress ipAddr;
        try {
                ipAddr = InetAddress.getLocalHost();
                System.out.println ("This is "+ipAddr);
        } catch (UnknownHostException e) {
                System.out.println ("Unknown host");
        }
    }
}

Source Code: Src/16/HostInfo.java

% java HostInfo
This is yps/129.21.38.198

18.18.  Daytime Client

Src/16/DayTime.java.minusSTART_STOP


import java.net.*;
import java.io.*;
import java.util.*;
public class DayTime {

    String hostName = "yps";
    int    port = 13;

    private void printMessage() {
        System.out.println("-h          ---->   help");
        System.out.println("[-host              hostName]");
        System.out.println("[-port              port]");
   }
        
   /**
     * Parse the commandlind arguments and sets variables.
     */
   public void parseArgs(String args[]) {

        for (int i = 0; i < args.length; i ++) {
                if (args[i].equals("-h")) 
                        printMessage();
                else if (args[i].equals("-host")) 
                        hostName = args[++i];
                else if (args[i].equals("-port")) 
                        port = new Integer(args[++i]).intValue();
        }
   }

   public void doTheJob()       {
        try {
                System.out.println("host: " +  hostName );
                System.out.println("port: " +  port );
                Socket sock = new Socket(hostName, port);
                
                BufferedReader din = new BufferedReader (
                        new InputStreamReader (sock.getInputStream()));
                String rTime = din.readLine ();
                System.out.println (rTime);
                sock.close();
        } catch (Exception e) {
                System.out.println (e);
        }
   }

   public static void main(String argv[]) {
        DayTime aDayTime = new DayTime();
        aDayTime.parseArgs(argv);
        aDayTime.doTheJob();

   }
}

Source Code: Src/16/DayTime.java

% java DayTime 
host: yps
port: 13
Mon Oct 24 09:05:49 EDT 2005

18.19.  Daytime Server

Src/16/DayTimeServer.java.minusSTART_STOP


import java.net.*;
import java.io.*;
import java.util.*;

public class DayTimeServer extends Thread {

   ServerSocket         listen;
   int                  port     = 4242;

   public DayTimeServer()       {
   }

   public DayTimeServer(int port)       {
        try { 
            listen = new ServerSocket(port);
            System.out.println ("2: Listening on port: "
                + listen.getLocalPort());
        } catch(Exception e) {
            System.out.println(e);
        }
   }

    private void printMessage() {
        System.out.println("-h          ---->   help");
        System.out.println(" -port              port");
        System.out.println(" {-port             port}");
        System.out.println("or ");
        System.out.println(" no argument");
   }
        
   /**
     * Parse the commandlind arguments and sets variables.
     */
   private  void parseArgs(String args[]) {

        for (int i = 0; i < args.length; i ++) {
                if (args[i].equals("-h")) 
                        printMessage();
                else if (args[i].equals("-port")) {
                        port = new Integer(args[++i]).intValue();
                        new DayTimeServer(port).start();
                }
        }
   }
   
   public void run()    {
        try {
            for(;;) {
                Socket clnt = listen.accept();
                System.out.println(clnt.toString());
                PrintWriter out = new PrintWriter
                    (clnt.getOutputStream (), true);
                out.println("It is now: " + new Date());
                clnt.close();
            }
        } catch(Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
   }

    public static void main(String argv[]) {
        if ( argv.length == 0 )
                new DayTimeServer(0).start();
        else
                new DayTimeServer().parseArgs(argv);
    }
}

Source Code: Src/16/DayTimeServer.java

% # Window 1
java DayTimeServer
Socket[addr=/129.21.36.168,port=63941,localport=63931]
Socket[addr=/129.21.36.168,port=63950,localport=63931]
 ...


% # Window 2
% telnet yps.cs.rit.edu 63931
Trying 129.21.36.168...
Connected to yps.
Escape character is '^]'.
Mon Oct 24 09:05:51 EDT 2005
Connection to yps closed by foreign host.

% java DayTime
host: holly.cs.rit.edu
port: 13
Mon Oct 24 09:05:52 EDT 2005

%  java DayTime -host yps
host: yps
port: 13
java.net.ConnectException: Connection refused

% java DayTime -host yps -port 63931
host: yps
port: 63931
Mon Oct 24 09:05:54 EDT 2005

% 

18.20.  Reading from and Writing to a Socket

Src/16/HpEchoSocketTest.java.minusSTART_STOP


import java.io.*;
import java.net.*;

class HpEchoSocketTest {

       Socket s;
       String hostname;
       int port;
       PrintWriter out = null;
        BufferedReader in = null;


       public void readAndPrint() throws Exception {
              InputStream ins;
              OutputStream os;

              BufferedReader stdIn = new BufferedReader(
                                   new InputStreamReader(System.in));
                String userInput;

                    while ((userInput = stdIn.readLine()) != null) {
                        out.println(userInput);
                        System.out.println("echo: " + in.readLine());
                    }
              stdIn.close();
       }

///////////////////////////////////////////////


       public HpEchoSocketTest(String name, int port) {
              hostname = name;
              this.port = port;
              try {
                     s = new Socket(hostname, port);
                     out = new PrintWriter(
                            s.getOutputStream(), true);
                        in = new BufferedReader(
                              new InputStreamReader(
                                          s.getInputStream()));
                     readAndPrint();
                     in.close();
                     out.close();
              } catch (Exception e )       {
                     System.out.println(e.toString());
                     System.exit(1);
              }
       }

       public static void main(String[] args) {
              HpEchoSocketTest st;
              String host = "holly";
              int    port = 7;

              st = new HpEchoSocketTest(host, port);
       }

}

Source Code: Src/16/HpEchoSocketTest.java

This client program is straightforward and simple because the Echo server implements a simple protocol. The client sends text to the server, and the server echoes it back.

These are the typical steps:

1.
Open a socket.
2.
Open an input stream and output stream to the socket.
3.
Read from and write to the stream according to the server's protocol.
4.
Close the streams.
5.
Close the socket.

18.21.  Connection to an URL

Class URL represents a Uniform Resource Locator, a pointer to a "resource" on the World Wide Web. A resource can be something as simple as a file or a directory, or it can be a reference to a more complicated object, such as a query to a database or to a search engine. More information on the types of URLs and their formats can be found at: http://www.ncsa.uiuc.edu/demoweb/url-primer.html

Src/16/Url_Read.java.minusSTART_STOP


import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;

public class Url_Read {

  public static void readFromUrl(String theUrl) {
  
  URL aUrl = null;
  BufferedReader in = null;
  String line;
  
  try {
          aUrl = new URL(theUrl);
          System.out.println("getPort() " + aUrl.getPort());
          System.out.println("getHost() " + aUrl.getHost());
          System.out.println("getProtocol() " + aUrl.getProtocol());
          System.out.println("getFile() " + aUrl.getFile());
          System.out.println("getRef() " + aUrl.getRef());

          in = new BufferedReader(
                   new InputStreamReader( aUrl.openStream() ) );

          while ( ( line = in.readLine() ) != null ) {
                System.out.println(line);
          }

          in.close();
          
  } catch (MalformedURLException e) {
          System.err.println("Something is wrong with this " +
                theUrl +  ".");
          System.exit(1);
  } catch (IOException e) {
          System.err.println("Couldn't get I/O for the connection to: "
                + theUrl );
          System.exit(1);
  }
  
  }

  public static void main( String args[] ) {

    if ( args.length != 1 )     {
        System.err.println(
             "Usage: java Url_Read url");
        System.exit(1);
    }

    try {
        readFromUrl(args[0]);
        
    }
    catch ( NumberFormatException e)    {
        System.out.println(args[0] + " is not a number ;-(");
    }

  }
}

Source Code: Src/16/Url_Read.java

% java Url_Read http://www.cs.rit.edu/~hpb | sed 15q
getPort() -1
getHost() www.cs.rit.edu
getProtocol() http
getFile() /~hpb
getRef() null
<HTML>

<HEAD>
<title>Hans-Peter Bischof's Home Page</title>
</HEAD>


<FRAMESET cols="230,*">
  <frame name="toc"    TARGET="_main" src="toc.html"     scrolling="auto">
  <frame name="intro"                 src="intro.html"   scrolling="auto">

18.22.  Multi Client Server and Client

18.23.  Datagram Socket

An example:

Src/16/DayTimeUDPServer.java.minusSTART_STOP


import java.net.*;
import java.io.*;
import java.util.*;

public class DayTimeUDPServer extends Thread {

   DatagramSocket       socket;
   static String        hostName = "yps";
   int                  port     = 4242;


   public DayTimeUDPServer()    {
   }

   public DayTimeUDPServer(int port)    {
        try { 
            socket = new DatagramSocket(port);
            System.out.println ("Listening on port: "
                + socket.getLocalPort());
        } catch(Exception e) {
            System.out.println(e);
        }
   }

    private void printMessage() {
        System.out.println("-h          ---->   help");
        System.out.println("[-host              hostName");
        System.out.println(" -port              port");
        System.out.println(" {-port             port}");
        System.out.println("or ");
        System.out.println(" no argument");
   }
        
   /**
     * Parse the commandlind arguments and sets variables.
     */
   public void parseArgs(String args[]) {

        for (int i = 0; i < args.length; i ++) {
                if (args[i].equals("-h")) 
                        printMessage();
                else if (args[i].equals("-host")) 
                        hostName = args[++i];
                else if (args[i].equals("-port")) {
                        port = new Integer(args[++i]).intValue();
                        new DayTimeUDPServer(port).start();
                }
        }
   }
   
   public void run()    {
        byte[] buf = new byte[256];
        try {
            for(;;) {
                String sendThis = "es schlaegt: " + new Date();
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                InetAddress address = packet.getAddress();
                int port = packet.getPort();
                buf = sendThis.getBytes();
                packet = new DatagramPacket(buf, buf.length, address, port);
                System.out.println("Sending to port: " + port );
                System.out.println("Sending    data: " + new String(buf) );
                socket.send(packet);
            }
        } catch(Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
   }

    public static void main(String argv[]) {
        if ( argv.length == 0 )
                new DayTimeUDPServer(0).start();
        else
                new DayTimeUDPServer().parseArgs(argv);
    }
}

Source Code: Src/16/DayTimeUDPServer.java

Src/16/DayTimeUDP.java.minusSTART_STOP


import java.net.*;
import java.io.*;
import java.util.*;
public class DayTimeUDP {

    String hostName = "yps";
    int    port = 13;

    private void printMessage() {
        System.out.println("-h          ---->   help");
        System.out.println("[-host              hostName]");
        System.out.println("[-port              port]");
   }
        
   /**
     * Parse the commandlind arguments and sets variables.
     */
   public void parseArgs(String args[]) {

        for (int i = 0; i < args.length; i ++) {
                if (args[i].equals("-h")) 
                        printMessage();
                else if (args[i].equals("-host")) 
                        hostName = args[++i];
                else if (args[i].equals("-port")) 
                        port = new Integer(args[++i]).intValue();
        }
   }

   public void doTheJob()       {
        try {
                byte buf[] = new byte[64];
                InetAddress aInetAddress = InetAddress.getByName(hostName);
                DatagramPacket dp = new DatagramPacket(buf, buf.length);
                DatagramSocket socket = new DatagramSocket();
                DatagramPacket packet = new DatagramPacket(buf,
                        buf.length, aInetAddress, port);
                socket.send(packet);

                System.out.println("host: " +  hostName );
                System.out.println("port: " +  port );
                System.out.println("after creation");
                socket.receive(dp);
                System.out.println("received: -" +
                        new String(dp.getData() ) + "-"  );
                socket.close();
        } catch (Exception e) {
                System.out.println (e);
                e.printStackTrace();
        }
   }

   public static void main(String argv[]) {
        DayTimeUDP aDayTimeUDP = new DayTimeUDP();
        aDayTimeUDP.parseArgs(argv);
        aDayTimeUDP.doTheJob();

   }
}

Source Code: Src/16/DayTimeUDP.java

18.24.  Remote Method Invocation

See also http://java.sun.com/docs/books/tutorial/rmi.

Part of the text and programs are from there. Copyright belongs to Ann Wollrath and Jim Waldo.

See also http://java.sun.com/products/jdk/1.2/docs/guide/rmi/.

The Java Remote Method Invocation (RMI) system allows an object running in one Java Virtual Machine (VM) to invoke methods on an object running in another Java VM. RMI provides for remote communication between programs written in the Java programming language.

Distributed object applications need to:

Locate remote objects

Applications can use one of two mechanisms to obtain references to remote objects. An application can register its remote objects with RMI's simple naming facility, the rmiregistry, or the application can pass and return remote object references as part of its normal operation.
Communicate with remote objects

Details of communication between remote objects are handled by RMI; to the programmer, remote communication looks like a standard Java method invocation.
Load class bytecodes for objects that are passed as parameters or return values

Because RMI allows a caller to pass pure Java objects to remote objects, RMI provides the necessary mechanisms for loading an object's code as well as transmitting its data.

The illustration below depicts an RMI distributed application that uses the registry to obtain references to a remote object. The server calls the registry to associate a name with a remote object. The client looks up the remote object by its name in the server's registry and then invokes a method on it.

18.25.  Remote Method Invocation: Idea

The problem is: you need a reference of an object, before you can send a method to it.

18.26.  Remote Method Invocation: Idea II

18.27.  SenderProxy/Receiver Proxy

18.28.  SenderProxySource Code

 ....
    private static final long INTERFACE_ID = 32;
    private final long m2mic__String__METHOD_1 = 0;

 ...
public void knockKnock( String _0)  {
    try {
        ByteArrayOutputStream aS = new ByteArrayOutputStream(1024);
        ObjectOutputStream p = new ObjectOutputStream(aS);
        p.writeObject(_0);
        p.close();
        RmiPacket aRmiPacket = new RmiPacket( INTERFACE_ID,
                                        m2mic__String__METHOD_1,
                                        aS.toByteArray() );
        netWorkCommEndPoint.sendDataToMany(aRmiPacket);
        e.printStackTrace();
        System.exit(1);
    }
}

18.29.  ReceiverProxySource Code

 ....
    private static final long INTERFACE_ID = 32;
    private final long m2mic__String__METHOD_1 = 0;
    
    RmiPacket aRmiPacket = null;
            
    aRmiPacket = aM2mCommEndPoint.readData();
    theData = aRmiPacket.getData();
    if ( aRmiPacket.getMethodId() == m2mic__String__METHOD_1) {
                        String __0 = (String)ip.readObject();
                        aThisClass.knockKnock(__0);
    }
 ...

rmic generates the Sender and ReceiverProxys.

18.30.  Remote Method Invovation Registry

Where does the sender proxy come from?

18.31.  Passing Non-remote Objects

A non-remote object, that is passed as a parameter of a remote method invocation or returned as a result of a remote method invocation, is passed by copy; that is, the object is serialized using the Java Object Serialization mechanism.

So, when a non-remote object is passed as an argument or return value in a remote method invocation, the content of the non-remote object is copied before invoking the call on the remote object.

When a non-remote object is returned from a remote method invocation, a new object is created in the calling virtual machine

18.32.  Advantages of Dynamic Code Loading

18.33.  Remote Interfaces, Objects, and Methods

--
A remote interface extends the interface java/rmi.Remote.
--
Each method of the interface declares java/rmi.RemoteException in its throws clause, in addition to any application-specific exceptions.

18.34.  RMI && JDK 1.5

RMI has been enhanced in the following areas:

Stolen from: http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html#rmi

18.35.  Creating Distributed Applications Using RMI

1.
Design and implement the components of your distributed application.
2.
Compile sources and generate stubs.
3.
Make classes network accessible.
4.
Start the application.

Compile Sources and Generate Stubs

This is a two-step process. In the first step you use the javac compiler to compile the source files, which contain the implementation of the remote interfaces and implementations, the server classes, and the client classes. In the second step you use the rmic compiler to create stubs for the remote objects. RMI uses a remote object's stub class as a proxy in clients so that clients can communicate with a particular remote object.

Make Classes Network Accessible

In this step you make everything--the class files associated with the remote interfaces, stubs, and other classes that need to be downloaded to clients.

Start the Application

Starting the application includes running the RMI remote object registry, the server, and the client.

18.36.  Intro Example

We have to design a protocol that allows jobs to be submitted to the server and results of the job to be returned to the client. This protocol is expressed in interfaces supported by the server and by the objects that are submitted to the sever, as shown in the following figure.

[picture]

18.37.  Hello World

The Client:

Src/16_D/HelloC.java.minusSTART_STOP


import java.rmi.*;

public class HelloC {
        public static void main(String args[] ) {
        String message = "";
        try {
                HelloInterface obj = (HelloInterface)Naming.
                                lookup("//aragorn/IamAhelloImplementationObject");

                message = obj.sayHello();

                System.out.println(message);

        } catch (Exception e) {
                System.out.println("HelloC exception: " +
                e.getMessage());
                e.printStackTrace();
        }
  }
}

Source Code: Src/16_D/HelloC.java The interface:

Src/16_D/HelloInterface.java.minusSTART_STOP


public interface HelloInterface extends java.rmi.Remote {
        String sayHello() throws java.rmi.RemoteException;
}

Source Code: Src/16_D/HelloInterface.java

The implementation of the interface:

Src/16_D/HelloImplementation.java.minusSTART_STOP


import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class HelloImplementation
        extends UnicastRemoteObject
        implements HelloInterface {

        public HelloImplementation() throws RemoteException {
        }

        public String sayHello() throws RemoteException {
                return  "Hello World my friend.";
        }
}

Source Code: Src/16_D/HelloImplementation.java

The implementation of the server:

Src/16_D/HelloServer.java.minusSTART_STOP


import java.rmi.*;

public class HelloServer {

        public static void main(String args[])
        {
                // System.setSecurityManager(new RMISecurityManager());

                try {
                    HelloInterface obj = new HelloImplementation();
                    Naming.rebind("//aragorn/IamAhelloImplementationObject", obj);
                    System.out.println("HelloServer bound in registry");
                } catch (Exception e) {
                    System.out.println("HelloImpl err: " + e.getMessage());
                    e.printStackTrace();
                }
        }
}

Source Code: Src/16_D/HelloServer.java

RMISecurityManager

The RMISecurityManager class defines a default security policy for RMI applications (not applets). For code loaded from a class loader, the security manager disables all functions except class definition and access. This class may be subclassed to implement a different policy. To set a RMISecurityManager, add the following to an application's main() method:

System.setSecurityManager(new RMISecurityManager());

If no security manager has been set, RMI will only load classes from local system files as defined by CLASSPATH.

Naming

is the bootstrap mechanism for obtaining references to remote objects based on Uniform Resource Locator (URL) syntax. The URL for a remote object is specified using the usual host, port and name:

rmi://host:port/name 
host = host

name of registry (defaults to the current host) port = port
number of registry (defaults to the registry port number) name = name
for remote object

The makefile:

 1      
 2      all:
 3        rmic HelloImpl
 4        rmiregistry &
 5        sleep 1
 6        javac HelloImpl.java
 7        java HelloImpl &
 8        sleep 4
 9        javac HelloC.java
10        java HelloC
11      

Source Code: Src/16_D/Makefile

% make -f Makefile
rmic HelloImpl
rmiregistry &
javac HelloImpl.java
java HelloImpl &
sleep 4
HelloServer bound in registry
javac HelloC.java
java HelloC
Hello World my friend.

Note: Make sure that rmiregistry is dead before you log out!

Note: Make sure that every java server is dead before you log out!

 1      #!/bin/sh
 2      
 3      TO_FIND="registry"
 4      if [ $# -eq 1 ]
 5      then
 6              if [ $1 -eq "java" ]
 7              then
 8                      TO_FIND="java"
 9              fi
10      fi
11      
12      
13      ps -edf                 |       \
14      grep $TO_FIND           |       \
15      grep -v grep            |       \
16      grep -v kill            |       \
17      grep -v vi              |       \
18      awk ' { print $2 }'     |       \
19      while read x
20      do
21              echo "kill -9 $x"
22              kill -9 $x 2> /dev/null
23      done
24      
25      exit 0

Source Code: Src/16_D/killIt

% ps -edf | grep java

The improved makefile:

Source Code: Src/16_D/makefile

% make
rmic HelloImpl
javac HelloC.java
rmiregistry &
sleep 1
java HelloImpl &
sleep 4
        HelloImpl: HelloImpl(String s)
HelloServer bound in registry
java HelloC
Hello World my friend.
killIt java
kill -9 26491
kill -9 26489
kill -9 26438
kill -9 26332
kill -9 26501
Killed
killIt 
Killed

The registry by default runs on port 1099. To start the registry on a different port, specify the port number in the command. For example, to start the registry on port 2001:

% rmiregistry 2001

For example, if the registry is running on port 2001 in the Hello World example, here is the call required to bind HelloServer to the remote object reference:

Naming.lookup("//yps:2001/HelloServer", obj);

18.38.  Hello World II

The Client:

Src/16_P/HelloC.java.minusSTART_STOP


import java.rmi.*;

public class HelloC {
        public static void main(String args[] ) {
        String message = "";
        try {
                Hello obj =
                         (Hello)Naming.lookup("//yps:2001/HelloServer");

                message = obj.sayHello();

                System.out.println(message);

        } catch (Exception e) {
                System.out.println("Something went wrong: " +
                        e.getMessage());
                e.printStackTrace();
        }
  }
}

Source Code: Src/16_P/HelloC.java

The Server:

Src/16_P/HelloImpl.java.minusSTART_STOP


import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class HelloImpl
        extends UnicastRemoteObject
        implements Hello
{
        private String name;

        public HelloImpl(String s) throws RemoteException {
                name = s;
        }

        public String sayHello() throws RemoteException {
                return  "Stanley Kubrick was there!";
        }

        public static void main(String args[])
        {
                // Create and install a security manager
                // System.setSecurityManager(new RMISecurityManager());

                try {
                        HelloImpl obj = new HelloImpl("HelloServer");
                        Naming.rebind("//yps:2001/HelloServer", obj);
                        System.out.println("HelloServer bound in registry");
                } catch (Exception e) {
                        System.out.println("HelloImpl err: " + e.getMessage());
                        e.printStackTrace();
                }
        }
}

Source Code: Src/16_P/HelloImpl.java

The interface:

Src/16_P/Hello.java.minusSTART_STOP


public interface Hello extends java.rmi.Remote {
        String sayHello() throws java.rmi.RemoteException;
}

Source Code: Src/16_P/Hello.java

The makefile:

 1      
 2      
 3      all: Hello.class HelloC.class HelloImpl.class   \
 4           HelloImpl_Skel.class HelloImpl_Stub.class
 5      
 6              rmiregistry 2001 &
 7              sleep 1
 8              java HelloImpl &
 9              sleep 4
10              java HelloC
11              killIt java
12              killIt
13      
14      
15      HelloImpl_Skel.class HelloImpl_Stub.class: HelloImpl.java
16              rmic HelloImpl
17      
18      Hello.class:    Hello.java
19              javac Hello.java
20      
21      HelloC.class:   HelloC.java
22              javac HelloC.java
23      
24      HelloImpl.class:        HelloImpl.java
25              javac HelloImpl.java
26              
27      clean:  
28              rm -f *class

Source Code: Src/16_P/makefile

18.39.  Multiple Servers

Client:

Src/16_M/Client.java.minusSTART_STOP


import java.rmi.*;

public class Client {
        public static void main(String args[] ) {
        String message = "";
        try {
                MyServer obj =
                         (MyServer)Naming.lookup("//yps:2001/Server1");
                message = obj.sayHello();
                System.out.println(message);


                obj = (MyServer)Naming.lookup("//yps:2001/Server2");
                message = obj.sayHello();
                System.out.println(message);

        } catch (Exception e) {
                System.out.println("Something went wrong: " +
                e.getMessage());
                e.printStackTrace();
        }
  }
}

Source Code: Src/16_M/Client.java

Server 1:

Src/16_M/Server1Impl.java.minusSTART_STOP


import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class Server1Impl
        extends UnicastRemoteObject
        implements MyServer
{
        private String name;

        public Server1Impl(String s) throws RemoteException {
                name = s;
        }

        public String sayHello() throws RemoteException {
                return  "Server1()";
        }

        public static void main(String args[])
        {
                // Create and install a security manager
                // System.setSecurityManager(new RMISecurityManager());

                try {
                        Server1Impl obj = new Server1Impl("Server1");
                        Naming.rebind("//yps:2001/Server1", obj);
                        System.out.println("Server1 bound in registry");
                } catch (Exception e) {
                        System.out.println("Server1Impl err: "
                           + e.getMessage());
                        e.printStackTrace();
                }
        }
}

Source Code: Src/16_M/Server1Impl.java

Server 2:

Src/16_M/Server2Impl.java.minusSTART_STOP


import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class Server2Impl
        extends UnicastRemoteObject
        implements MyServer
{
        private String name;

        public Server2Impl(String s) throws RemoteException {
                name = s;
        }

        public String sayHello() throws RemoteException {
                return  "Server2()";
        }

        public static void main(String args[])
        {
                // Create and install a security manager
                // System.setSecurityManager(new RMISecurityManager());

                try {
                        Server2Impl obj = new Server2Impl("Server2");
                        Naming.rebind("//yps:2001/Server2", obj);
                        System.out.println("Server2Server bound in registry");
                } catch (Exception e) {
                        System.out.println("Server2Impl err: "
                           + e.getMessage());
                        e.printStackTrace();
                }
        }
}

Source Code: Src/16_M/Server2Impl.java

% make
rmic Server1Impl
rmic Server2Impl
javac Client.java
rmiregistry 2001 &
sleep 1
java Server1Impl &
java Server2Impl &
sleep 4
Server2Server bound in registry
Server1 bound in registry
java Client
Server1()
Server2()

18.40.  Running Multiple Server on different Machines

--
boot time
--
via inetd
--
"by hand"

18.41.  Startup Multiple Server on different Machines

Client: Src/16_MS/Client.java.minusSTART_STOP


import java.rmi.*;
import java.math.*;

public class Client {

    public static void doIt(String catServer, String mouseServer, int port) {

        MyServer aCatServer;
        MyServer aMouseServer;
        Point    aPoint = new Point(4, 2 );

        System.out.println("In Client: cat   is on: " + catServer );
        System.out.println("In Client: mouse is on: " + mouseServer );
        System.out.println("In Client: port     is: " + port );
        try {
                aCatServer = (MyServer)Naming.lookup("rmi://" +
                        catServer + ":" + port + "/CatServer");

                aMouseServer = (MyServer)Naming.lookup("rmi://" +
                        mouseServer + ":" + port + "/MouseServer");


// -------------- Cat --------------------
        System.out.println("In Client: aCatServer.movePoint(aPoint): " + 
             (aPoint = aCatServer.movePoint(aPoint)).toString() );
        System.out.println("In Client: aCatServer.movePoint(aPoint): " + 
                        aCatServer.movePoint(aPoint).toString() );
        System.out.println("In Client: aCatServer.movePoint(aPoint): " + 
                        aCatServer.movePoint(aPoint).toString() );

// -------------- Mouse --------------------

        System.out.println("In Client: aMouseServer.movePoint(aPoint): " + 
             (aPoint = aMouseServer.movePoint(aPoint)).toString() );
        System.out.println("In Client: aMouseServer.movePoint(aPoint): " + 
                        aMouseServer.movePoint(aPoint).toString() );
        System.out.println("In Client: aMouseServer.movePoint(aPoint): " + 
                        aMouseServer.movePoint(aPoint).toString() );



        } catch (Exception e) {
                System.out.println("Something went wrong: " +
                e.getMessage());
                e.printStackTrace();
        }

   }

    public static void main(String args[] ) {
    int    port   = 1099;
    String catServer   = "yps";
    String mouseServer = "yps";

    if ( args.length  >= 1 )
        catServer = args[0];
    if ( args.length  >= 2 )
        mouseServer = args[1];
    if ( args.length  == 3 )
        try {
                port = Integer.parseInt(args[2]);
        }
        catch ( NumberFormatException e )       {
                System.out.println("Hm , port = " +
                        args[2] + " is not valid.");
                System.exit(1);
        }
    
    if ( args.length  > 3 )     {
        System.out.println("Usage: " + 
                        "java Client [CatServer [MouseServer [port]]]");
        System.exit(1);
    }

    doIt(catServer, mouseServer, port);
  }
}

Source Code: Src//16_MS/Client.java

Interface:

Src/16_MS/MyServer.java.minusSTART_STOP


public interface MyServer extends java.rmi.Remote {
        Point movePoint(Point aPoint) throws java.rmi.RemoteException;
        int getX()                    throws java.rmi.RemoteException;
        int getY()                    throws java.rmi.RemoteException;
}

Source Code: Src//16_MS/MyServer.java

Cat Server

Src/16_MS/CatServer.java.minusSTART_STOP


import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class CatServer extends UnicastRemoteObject implements MyServer
{
        final private int DELTA = 10;
        private int x;
        private int y;
        private Point aPoint;

        public CatServer() throws RemoteException {
                ;
        }


        public Point movePoint(Point aPoint) throws RemoteException {
                System.out.println("\tIN CatServer: movePoint(): "
                        + aPoint.toString() );
                return aPoint.move(DELTA, DELTA);
        }
        public int getX() throws RemoteException {
                System.out.println("\tCIN atServer: getX(): " + x );
                return  x;
        }

        public int getY() throws RemoteException {
                System.out.println("\tCIN atServer: getY(): " + y );
                return  x;
        }

public static void main(String args[])
  {
          int port = 1099;

          // System.setSecurityManager(new RMISecurityManager());

          if ( args.length  == 1 )
                  try {
                          port = Integer.parseInt(args[0]);
                   }
                   catch ( NumberFormatException e )    {
                          System.out.println("Hm , port = " +
                          args[0] + " is not valid.");
                          System.exit(1);
                    }
           
          try {
                  CatServer obj = new CatServer();
                  System.out.println("\tIN CatServer: " +
                                "rmi://:" + port + "/CatServer");
                  Naming.rebind("rmi://:" + port + "/CatServer", obj);
                  System.out.println("\tIN CatServer bound in registry");
          } catch (RemoteException  e) {
                  System.out.println("CatServer RemoteException ");
                  e.printStackTrace();
          } catch (Exception e) {
                  System.out.println("CatServer err: "
                  + e.getMessage());
                  e.printStackTrace();
          }
  }
}

Source Code: Src//16_MS/CatServer.java

Point Class:

Src/16_MS/Point.java.minusSTART_STOP


/**
 * This class implements a point in a two dimensional
 * area.
 * All methods print the method name, when they are called.
 * state information includes:
 *
 * @version   $Id$
 *
 * RIT's home page: <a href="http://www.cs.rit.edu/~hpb">RIT</a>
 *
 * Revisions:
 *      $Log$
 */
import java.io.*;


public class Point implements Serializable {

  private int x;                // x coordinate of the point
  private int y;                // y cooridnate of the point

/**
 * Constructor.
 * initialize x and y values of a point
 *
 * @param       x       x coordinate
 * @param       y       y coordinate
 *
 * @return      a Point object
 */
  public Point(int _x, int _y){
        this.x = _x;
        this.y = _y;
  }

  private void writeObject(ObjectOutputStream s) throws IOException {
           s.defaultWriteObject();
  }

  private void readObject(ObjectInputStream s) throws IOException  {
        try {
                s.defaultReadObject();
        }
        catch ( ClassNotFoundException e)       {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
  }
/**
 * initialzes x and y of a point.
 *
 * @param       x       int x coordinate
 * @param       y       int y coordinate
 *
 * @return      a Point object
 */
  public Point initPoint(int _x, int _y){

        this.x = _x;
        this.y = _y;

        return this;
  }

/**
 * moves a point
 *
 * @param       _x      int delta x value
 * @param       _y      int delta y value
 *
 * @return      a Point object
 */
  public Point move(int _x, int _y){

        this.x += _x;
        this.y += _y;
        return this;
  }

/**
 * Returns the x coordinate of a point
 *
 * @return x value 
 */
  public int getX(){
        return this.x;
  }

/**
 * Returns the y coordinate of a point
 *
 * @return y value 
 */
  public int getY(){
        return this.y;
  }

/**
 * Returns a String reperesentation of the point
 *
 * @return String reprasentation of the point
 */
  public String toString(){
        return "Point at (" + x + "/" + y + ")";
  }
}

Source Code: Src/16_MS/Point.java

Makefile:

 1      
 2      
 3      all: Point.class                                        \
 4           CatServer_Skel.class CatServer_Stub.class  \
 5           MouseServer_Skel.class MouseServer_Stub.class      \
 6           MyServer.class Client.class                        
 7      
 8              fireItUp
 9      
10      
11      CatServer_Skel.class CatServer_Stub.class: CatServer.java
12              rmic CatServer
13      MouseServer_Skel.class MouseServer_Stub.class: MouseServer.java
14              rmic MouseServer
15      
16      MyServer.class: MyServer.java
17              javac MyServer.java
18      
19      Client.class:   Client.java
20              javac Client.java
21      
22      CatServer.class:        CatServer.java
23              javac CatServer.java
24      
25      MouseServer.class:      MouseServer.java
26              javac MouseServer.java
27              
28      Point.class:    Point.java
29              javac Point.java
30              
31      clean:
32              rm -f *class

Source Code: Src/16_MS/makefile

Result:

        IN CatServer: //yps:2001/CatServer
        IN MouseServer: /yps:2001/MouseServer
        IN CatServer bound in registry
In Client: cat   is on: yps
In Client: mouse is on: yps
In Client: port     is: 2001
        IN MouseServer bound in registry
        IN CatServer: movePoint(): Point at (4/2)
In Client: aCatServer.movePoint(aPoint): Point at (14/12)
        IN CatServer: movePoint(): Point at (14/12)
In Client: aCatServer.movePoint(aPoint): Point at (24/22)
        IN CatServer: movePoint(): Point at (14/12)
In Client: aCatServer.movePoint(aPoint): Point at (24/22)

Start of a fireItUp Script:

 1      #!/bin/sh
 2      
 3      KILL_IT="killIt; killIt java"
 4      ME="`who am i | sed 's/ .*//'`"
 5      HOSTNAME="`hostname`"
 6      USEDHOSTS="yps yps yps" # <-- modify here ...
 7      WD=`pwd`
 8      
 9      
10      remote_cmd()            # bg host cmd
11      {
12              echo "$HOSTNAME $ME" > $HOME/.rhosts
13              if [ $1 = "bg" ]
14              then
15                      rsh $2 "rm -f $HOME/.rhosts; cd $WD && $3" &
16              else
17                      rsh $2 "rm -f $HOME/.rhosts; cd $WD && $3" 
18              fi
19      }
20      
21      kill_all()
22      {
23              for i in $USEDHOSTS
24              do
25                      remote_cmd fg $i "$KILL_IT" 2>&1 > /dev/null
26              done
27      }
28      
29      
30      
31      
32      
33      
34      
35      
36      
37      
38      
39      
40      
41      
42      kill_all
43      sleep 2
44      
45      echo 1
46      rmiregistry & 
47      echo "Waiting for rmiregistry .... chrr ... "; sleep 1
48      java CatServer &
49      
50      echo 2
51      remote_cmd bg yps "rmiregistry &" 
52      
53      echo 3
54      echo "Waiting for rmiregistry .... chrr ... "; sleep 2
55      remote_cmd bg yps "java MouseServer &"
56      
57      echo 4
58      echo "Waiting for the servers  .... chrr ... "; sleep 2
59      remote_cmd fg yps "java Client $HOSTNAME stones"
60      
61      kill_all
62      
63      exit 0
64      

Source Code: Src/16_MS/fireItUp

18.42.  Calculating PI

% make
javac Client.java
rmiregistry &
sleep 1
java PiServer &
sleep 4
        PiServer: PiServer()
PiServer bound in registry
java Client
3.1415926536
% java Client 100
3.141592653589793238462643383279502884197
16939937510582097494459230781640628620899
86280348253421170680
% 

Server Interface:

Src/16_M/MyServer.java.minusSTART_STOP


public interface MyServer extends java.rmi.Remote {
        String sayHello() throws java.rmi.RemoteException;
}

Source Code: Src/16_M/MyServer.java

Class java/gmath.BigDecimal

Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer value and a non-negative integer scale, which represents the number of decimal digits to the right of the decimal point. (The number represented by the BigDecimal is intVal/7**scale.) BigDecimals provide operations for basic arithmetic, scale manipulation, comparison, format conversion and hashing. The compute engine, a remote object in the server, takes tasks from clients, runs them, and returns any results. The tasks are run on the machine where the server is running. This sort of distributed application could allow a number of client machines to make use of a particularly powerful machine or one that has specialized hardware.

Client:

Src/16_C/Client.java.minusSTART_STOP


import java.rmi.*;
import java.math.*;

public class Client {

    public static void doIt(String host, String port, int digits) {
        String message = "";
        try {
                MyServer obj = (MyServer)Naming.lookup("//" +
                        host + ":" + port + "/PiServer");
                System.out.println(obj.computePi(digits));

        } catch (Exception e) {
                System.out.println("Something went wrong: " +
                e.getMessage());
                e.printStackTrace();
        }

   }

    public static void main(String args[] ) {
    int    digits = 10;
    String host   = "yps";
    String port   = "";


    if ( args.length  >= 1 )    {
        try {
                digits = Integer.parseInt(args[0]);
        }
        catch ( NumberFormatException e )       {
                System.out.println("Hm , digits = " + args[0]);
                System.exit(1);
        }

    }
    if ( args.length >= 2 )     {
        host = args[1];
    }

    if ( args.length  == 3 )    {
        try {
                port = args[2];
                Integer.parseInt(port);
        }
        catch ( NumberFormatException e )       {
                System.out.println("Port = " + port + " is not valid.");
                System.exit(1);
        }

    }
    if ( args.length  > 3 )     {
        System.out.println("Usage: java Client [digits [host [port]]]");
        System.exit(1);
    }
    doIt(host, port, digits);
  }
}

Source Code: Src/16_C/Client.java Interface:

Src/16_C/MyServer.java.minusSTART_STOP


import java.math.*;

public interface MyServer extends java.rmi.Remote {
        BigDecimal computePi(int digits)
        throws java.rmi.RemoteException;
}

Source Code: Src/16_C/MyServer.java

Server:

Src/16_C/PiServer.java.minusSTART_STOP


import java.rmi.*;
import java.math.*;
import java.rmi.server.UnicastRemoteObject;

public class PiServer
        extends UnicastRemoteObject
        implements MyServer
{
    /** constants used in pi computation */
    private static final BigDecimal ZERO = 
        BigDecimal.valueOf(0);
    private static final BigDecimal  ONE = 
        BigDecimal.valueOf(1);
    private static final BigDecimal FOUR = 
        BigDecimal.valueOf(4);

    /** rounding mode to use during pi computation */
    private static final int roundingMode = 
        BigDecimal.ROUND_HALF_EVEN;

    /** digits of precision after the decimal point */
    private int digits;
    

    /**
     * Construct a task to calculate pi to the specified
     * precision.
     */
    public PiServer() throws RemoteException {
        System.out.println("\tPiServer: PiServer()");
    }
    /**
     * Compute the value of pi to the specified number of 
     * digits after the decimal point.  The value is 
     * computed using Machin's formula:
     *
     *          pi/4 = 4*arctan(1/5) - arctan(1/239)
     *
     * and a power series expansion of arctan(x) to 
     * sufficient precision.
     */
    public BigDecimal computePi(int digits) throws RemoteException {
        int scale = digits + 5;
        BigDecimal arctan1_5 = arctan(5, scale);
        BigDecimal arctan1_239 = arctan(239, scale);
        BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
                                  arctan1_239).multiply(FOUR);
        return pi.setScale(digits, 
                           BigDecimal.ROUND_HALF_UP);
    }
    /**
     * Compute the value, in radians, of the arctangent of 
     * the inverse of the supplied integer to the speficied
     * number of digits after the decimal point.  The value
     * is computed using the power series expansion for the
     * arc tangent:
     *
     * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + 
     *     (x^9)/9 ...
     */   
    public static BigDecimal arctan(int inverseX, 
                                  int scale) 
    {
        BigDecimal result, numer, term;
        BigDecimal invX = BigDecimal.valueOf(inverseX);
        BigDecimal invX2 = 
            BigDecimal.valueOf(inverseX * inverseX);

        numer = ONE.divide(invX, scale, roundingMode);

        result = numer;
        int i = 1;
        do {
            numer = 
                numer.divide(invX2, scale, roundingMode);
            int denom = 2 * i + 1;
            term = 
                numer.divide(BigDecimal.valueOf(denom),
                             scale, roundingMode);
            if ((i % 2) != 0) {
                result = result.subtract(term);
            } else {
                result = result.add(term);
            }
            i++;
        } while (term.compareTo(ZERO) != 0);
        return result;
    }


        public static void main(String args[])
        {
                // Create and install a security manager
                // System.setSecurityManager(new RMISecurityManager());

                try {
                        PiServer obj = new PiServer();
                        Naming.rebind("//yps:2042/PiServer", obj);
                        System.out.println("PiServer bound in registry");
                } catch (Exception e) {
                        System.out.println("PiServer err: " + e.getMessage());
                        e.printStackTrace();
                }
        }
}

Source Code: Src/16_C/PiServer.java

18.43.  Receiving and Sending Objects

Interface:

Src/16_Hash/HashTableInterface.java.minusSTART_STOP


import java.util.*;

public interface HashTableInterface extends java.rmi.Remote {
    Hashtable playWithAHashTable(String t)
                throws java.rmi.RemoteException;
}

Source Code: Src/16_Hash/HashTableInterface.java

Client:

Src/16_Hash/HashTableC.java.minusSTART_STOP


import java.rmi.*;
import java.util.*;

public class HashTableC {
        public static void main(String args[] ) {
        String plusMovie = "Smoke Signals";
        Hashtable aHashTable = new Hashtable();
        aHashTable.put("plusplus  Movie", "Comedian Harmonists");

        System.out.println("Client: aHashTable local = " +
                        aHashTable.toString());
        try {

                HashTableInterface obj =
                         (HashTableInterface)Naming.lookup("//yps/HelloServer");

                aHashTable = obj.playWithAHashTable(plusMovie);

        } catch (Exception e) {
                System.out.println("HelloApplet exception: " +
                e.getMessage());
                e.printStackTrace();
        }
        System.out.println("Client: aHashTable remote = " +
                        aHashTable.toString());
  }
}

Source Code: Src/16_Hash/HashTableC.java

Server:

Src/16_Hash/HashTableServer.java.minusSTART_STOP


import java.util.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class HashTableServer
        extends UnicastRemoteObject
        implements HashTableInterface {
        private String name;

        public HashTableServer(String s) throws RemoteException {
                System.out.println(
                   "\tHashTableServer: HashTableServer(String s)");
                name = s;
        }

        public Hashtable playWithAHashTable(String t)
                throws java.rmi.RemoteException {
                Hashtable aHashTable = new Hashtable();
                aHashTable.put("plusplus  Movie", t);
                System.out.println("\tserver: aHashTable = " +
                        aHashTable.toString());
                t = "done";
                return aHashTable;
        }
        public static void main(String args[])
        {
                // System.setSecurityManager(new RMISecurityManager());

                try {
                    HashTableServer obj = new HashTableServer("HelloServer");
                    Naming.rebind("//yps/HelloServer", obj);
                    System.out.println("HelloServer bound in registry");
                } catch (Exception e) {
                    System.out.println("HashTableServer err: " + e.getMessage());
                    e.printStackTrace();
                }
        }
}

Source Code: Src/16_Hash/HashTableServer.java

Result:

% make
rmic HashTableServer
javac HashTableC.java
rmiregistry &
sleep 1
java HashTableServer &
sleep 4
        HashTableServer: HashTableServer(String s)
HelloServer bound in registry
java HashTableC
Client: aHashTable = {plusplus  Movie=Comidian Harmonists}
        server: aHashTable = {plusplus  Movie=Smoke Signals}
Client: aHashTable = {plusplus  Movie=Smoke Signals}
Client: plusMovie = Smoke Signals
killIt java
kill -9 27386
Killed
killIt 
kill -9 27366
kill -9 27374
# make clean 

18.44.  RMI and Multi Threaded Systems

How does a remote method gets executed?

The Interface:

Src/16_T/MultiTInterface.java.minusSTART_STOP


public interface MultiTInterface extends java.rmi.Remote {
        String comeBackASAP() throws java.rmi.RemoteException;
        String sleepForAwhile() throws java.rmi.RemoteException;
}

Source Code: Src/16_T/MultiTInterface.java

The Client:

Src/16_T/MultiTC.java.minusSTART_STOP


import java.rmi.*;

public class MultiTC {
        public static void main(String args[] ) {
        String message = "";
        System.out.println("Going ... ");
        try {
                MultiTInterface obj =
                         (MultiTInterface)Naming.lookup("//spiegel:2001/MultiTServer");
                if ( args.length == 0 ) {
                        System.out.println("Call sleepForAwhile ...");
                        message = obj.sleepForAwhile();
                        System.out.println(message);
                } else  {
                        System.out.println("Call comeBackASAP ...");
                        message = obj.comeBackASAP();
                        System.out.println(message);
                }

        } catch (Exception e) {
                System.out.println("Something went wrong: " +
                        e.getMessage());
                e.printStackTrace();
        }
  }
}

Source Code: Src/16_T/MultiTC.java

The Server:

Src/16_T/MultiTImpl.java.minusSTART_STOP


import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class MultiTImpl
        extends UnicastRemoteObject
        implements MultiTInterface
{
        private String name;

        public MultiTImpl(String s) throws RemoteException {
                name = s;
        }

        public String sleepForAwhile() throws RemoteException {
                try { 
                        Thread.sleep(2000);
                } catch ( Exception e )         {
                        e.printStackTrace();
                }
                return  "sleepForAwhile";
        }

        public String comeBackASAP() throws RemoteException {
                return  "comeBackASAP";
        }

        public static void main(String args[])
        {
                try {
                        MultiTImpl obj = new MultiTImpl("MultiTServer");
                        Naming.rebind("//spiegel:2001/MultiTServer", obj);
                        System.out.println("MultiTServer bound in registry");
                } catch (Exception e) {
                        System.out.println("MultiTImpl err: " + e.getMessage());
                        e.printStackTrace();
                }
        }
}

Source Code: Src/16_T/MultiTImpl.java

The makefile:

 1      
 2      
 3      all: MultiTInterface.class MultiTC.class MultiTImpl.class       \
 4           MultiTImpl_Skel.class MultiTImpl_Stub.class
 5              rmiregistry 2001 &
 6              sleep 1
 7              java MultiTImpl &
 8              sleep 4
 9              java MultiTC 1 &
10              java MultiTC  &
11              killIt java
12              killIt
13      
14      
15      MultiTImpl_Skel.class MultiTImpl_Stub.class: MultiTImpl.java
16              rmic MultiTImpl
17      
18      MultiTInterface.class:  MultiTInterface.java
19              javac MultiTInterface.java
20      
21      MultiTC.class:  MultiTC.java
22              javac MultiTC.java
23      
24      MultiTImpl.class:       MultiTImpl.java
25              javac MultiTImpl.java
26              
27      clean:  
28              rm -f *class

Source Code: Src/16_T/makefile

18.45.  Dynamic Class Loading

RMI allows parameters, return values and exceptions passed in RMI calls to be any object that is serializable. RMI uses the object serialization mechanism to transmit data from one virtual machine to another and also annotates the call stream with the appropriate location information so that the class definition files can be loaded at the receiver.

When parameters and return values for a remote method invocation are unmarshalled to become live objects in the receiving VM, class definitions are required for all of the types of objects in the stream. The unmarshalling process first attempts to resolve classes by name in its local class loading context (the context class loader of the current thread). RMI also provides a facility for dynamically loading the class definitions for the actual types of objects passed as parameters and return values for remote method invocations from network locations specified by the transmitting endpoint. This includes the dynamic downloading of remote stub classes corresponding to particular remote object implementation classes (and used to contain remote references) as well as any other type that is passed by value in RMI calls, such as the subclass of a declared parameter type, that is not already available in the class loading context of the unmarshalling side.

To support dynamic class loading, the RMI runtime uses special subclasses of java/io.ObjectOutputStream and java/io.ObjectInputStream for the marshal streams that it uses for marshalling and unmarshalling RMI parameters and return values.


Weiter | Weiter | Weiter | Weiter | Kommentar


Created by unroff, java2html & & hp-tools. © by csfac. All Rights Reserved (2010).
It is not allowed to print these pages on a CAST printer.
Last modified 01/April/10