We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

HTTP Tunneling

sstephens
sstephens asked
on
Medium Priority
911 Views
Last Modified: 2011-09-20
OK - To implement HTTP tunneling, I need to set up a HTTPUrlSocket at each end, right?

Then I can send requests for pages one way, and the 'pages' themselves back the other way.

How do I implement this?  Say, for instance, that I want an Applet to send username and password details to a Server.  If the username and password are correct, the Server then returns some information (a booking calender) to the Applet.

I'm not really even sure how to start!

Does the applet need to send a request for:
http://blah.blah.blah.blah/blah #username;password?

How does the Server then pick this up (how do I code it)?

Does the Server still retain normal Netscape functions (we use it as a desktop machine as well)?

What formats can the Server return information in?

How can the Applet decode this information?

I am developing on a Unix, using a late-ish version of  JDK.  I am fairly OK with the concept of setting up a telnet server (ServerSocket/Socket - I've managed to set one of these up, but it doesn't work with Applets 'cause we've got a firewall).

Thanks, Shane
Comment
Watch Question

Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview

Commented:
Sorry for break in data. here is rest


asically the same
as the TestDataStream application we saw earlier. To recap, the flow of our client application is as follows:

          o Open an HTTP connection.

          o Format the request data.

          o Send the request to the server.

          o Read the response data.

          o Close the HTTP connection.

The server will simply read the request data and echo it back to the client.

Figure 10-17 shows the complete client application. To invoke the application you must supply the URL of the servlet that will echo the data:

          java javaservlets.tunnel.TestObjectStream

          http://larryboy/servlet/javaservlets.tunnel.ObjectStreamEcho

Note that the command has been split over multiple lines to improve readability; it should be entered as a single line. We will be using the ‘larryboy’ server
to invoke the ObjectStreamEcho servlet found in the javaservlets.tunnel package. The output from the application is shown in Figure 10-18.

Just like the TestDataStream application the data is being written to an in-memory buffer. Notice how we are using the generic ‘writeObject’ method found
in the ObjectInputStream class. The following description is given in the JDK documentation for ‘writeObject’:

          "Write the specified object to the ObjectOutputStream. The class of the object, the signature of the class, and the values of the non-transient
          and non-static fields of the class and all of its supertypes are written. Default serialization for a class can be overridden using the writeObject
          and the readObject methods. Objects referenced by this object are written transitively so that a complete equivalent graph of objects can be
          reconstructed by an ObjectInputStream."

What this means is that ‘writeObject’ causes the object to be serialized to the underlying output stream which then must be deserialized using the
‘readObject’ method of the ObjectInputStream class. The object should be read in the same order that they were written. However, serialization has one
distinct advantage over the simple marshaling that we have seen earlier; you can read a generic object and reflect upon the object to determine what type it
is (such as using the instanceof comparison operator).

The servlet used to read the response and echo the data is very similar to what we have seen before. Instead of using data input and output streams we’ll be
using object input and output streams. Figure 10-19 shows the source code for the ObjectStreamEcho servlet.

A tunnel client class for serialization

Writing the client implementation for our tunnel client that uses serialization is also very straight forward (see Figure 10-20). The only real difference
between this tunnel client and our ‘lite’ client that we developed earlier is the type of input and output streams that will be used. The base tunnel client does
not need to change since you had the foresight to separate the creation of the input and output streams from the base code (great job!).

A tunnel server class for serialization

As you might expect the implementation for the tunnel server that uses serialization is the same as the ‘lite’ version except that object input and output
streams are used (see Figure 10-21).

Tunneling example: RemoteIndy

To further illustrate the use of Java serialization let’s develop a simple applet that will use HTTP tunneling to make method calls to a server-side object that
will retrieve data from a database. The database contains a row for each year that the Indianapolis 500 was run; each row contains the year, the name of the
winning driver, and the average speed of the winning car.

Writing the server interface

Let’s start by writing an interface that describes the services available for our server-side object. By services I mean the methods, parameter types, and
return types of the server object. Our server object will provide the following services:

          o Initialize. Calling the initialize method will cause a database connection to be established and ready the object for use.

          o Query. The query method will accept a single parameter which will be used to form a SQL WHERE clause to select data out of the database.
          An object containing the selected data will be returned to the caller.

          o Close. Calling the close method will close the database connection and perform any necessary clean-up in the server object.

Figure 10-22 shows the code listing for the Indy interface. Notice that the query method returns an IndyRecord object. This object (shown in Figure
10-23) contains a public attribute for each column in the database. Notice that it implements java.io.Serializable; by doing so Java can properly serialize
and deserialize the object.

Note that to be a Java Beans compliant the IndyRecord class should really contain a ‘get’ and ‘set’ method for each of the properties; I have chosen to just
make the properties public so you can get the values directly.

Writing the server object

The beauty of writing the server object is that you do not need to know (or care) that the object will be used by HTTP tunneling; all we need to be
concerned about is implementing the interface. Figure 10-24 shows the implementation for the Indy object.

Notice that the initialize method is creating a database connection using the JDBC-ODBC Bridge and an Access database. Also, a JDBC
PreparedStatement object is being created as well. Preparing an SQL statement is a great way to boost performance for queries that you will be using
multiple times. In our case we’ll be re-executing the same query over and over with a different year value (this is done in the query method).

Note also how the data is being gathered from the result of the select statement in the query method. You should always retrieve column data in order and
each column should only be retrieved once; some JDBC drivers are rather strict in enforcing this requirement, especially the Bridge (due to the way ODBC
functions).

The close method simple ensures that the database connection is properly terminated. Make sure that you always close the database so that you don’t have
any unwanted memory leaks or wasted resources on the server.

Writing the client proxy

The client proxy is responsible for marshaling method and parameter data to the server and reading the return value from the response stream. Remember
that we’ve already done a lot of work in the base client object, so the client proxy is quite simple (see Figure 10-25). The constructor takes the base servlet
URL (such as http://larryboy/servlet/) and causes a new server-side object to be instantiated. The rest of the client proxy implementation is very repetitive;
because of this I’ve only included the query method.

Note that the method ordinal is unique within the method and is used to create the method header and how the object input and output streams are used to
marshal data back and forth to the server.

Writing the server stub

The server stub (which is also the servlet that will be invoked) implements the _getNewInstance and _invokeMethod routines. The _getNewInstance
method will return an instance of the Indy object that will be persisted with the HTTP session object in the Web server.

The _invokeMethod method will be given an instance of the server object (retrieved from the HTTP session), the method ordinal of the method to invoke
on the server object, an input stream to read parameters from, and an output stream which will be used to write return values. The RemoteIndyServer code
is shown in Figure 10-26.

Writing the applet

Now it’s time to put our remote object to use by writing a simple applet that uses the client proxy. Most of the work involved is in formatting the display;
calling methods on the remote object is nothing more than instantiating a new client proxy and making Java method calls on the Indy interface. Figure
10-27 shows the code for the Indy applet.

Note that the applet implements the ActionListener interface; doing so will force us to implement the actionPerformed method. After registering the applet
as a action listener for the button (addActionListener) the actionPerformed method will be called whenever the button is pressed. We can then perform
our query which will return the results from the database.

See it in action

After adding the RemoteIndyServer servlet to the Web server (via an alias) and writing a simple HTML page to load our applet (shown in Figure 10-28),
it’s time to give it a test drive. Don’t forget to place the applet and all supporting classes on your Web server’s class path so that the client browser can
locate them (or check out Chapter 12 to find out how to automatically create an archive file for distributing the applet). After entering the year, pressing
the ‘Query’ button will tunnel a method call to the servlet and display the results (see Figure 10-29).

Summary

In this chapter we’ve covered how to make remote method calls using HTTP tunneling. We’ve seen how to marshal data generically for all versions of the
JDK (which we called ‘lite’ version) as well as how to marshal data specifically for JDK 1.1 and higher. Along the way a base class was developed for both
the client and server which made writing client proxies and server stubs much easier. We also wrote applets to exercise the remote objects that were
developed; these applets can be deployed over the Internet very easily.

In the next chapter we’ll make developing remote objects painless by automating the process. You may have noticed that writing client proxies and server
stubs was somewhat repetitive; we’ll be developing an application that will automatically generate the source code for these classes by using Java reflection
to discover the methods, parameters, and return types of the server object.

Commented:
I got 'page not found' when I tried to follow the link http://www.pbg.mcgraw-hill.com/betabooks/moss/chap10.html .So, Figure xx could not be consulted.Can you give the current URL of that book?
In http/1.1 ,the concept of persistent connection comes, how to implement that?
Thanks for good explanation on tunneling.
Saadat
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.