Plug into Sockets
by Kevin Vandever
[The code for this article is available for download.]
Developers possess many tools for accessing the iSeries from the Web. I have written about many of those tools in this newsletter. But there are those out there who want to connect to many platforms or want to use a more core-Java approach to accessing the iSeries. They want pure portability but still require speed and ease of implementation. "The toolbox is great," they'll say, "but it is still platform-dependent." Well, that's OK, because I just may have what the Java developer ordered, in the form of sockets.
For what it's worth, I am still a big iSeries Java toolbox fan, but I can understand where these guys are coming from. Besides, sockets are cool and very easy to code in Java. So why not share the knowledge? A socket is basically an endpoint, a port that can be addressed in a network. You can use sockets to communicate with other sockets in a communication area. This area can be as large as the Internet or as small as any two points that can connect using TCP/IP. You can even use sockets to communicate between programs on the same machine, something I have done using RPG and Java on the AS/400.
Let's take a look at some of the advantages of sockets. First, sockets are portable; they are part of Java's core API and go everywhere Java goes. No extra toolkit or extensions are necessary to implement them. I have compiled and run a Java socket client on the AS/400 to communicate with an RPG socket host on the same AS/400. I then moved the client to a Windows NT server; it worked just as well with the socket host on the AS/400. Second, sockets are fast. How fast? Well, at least as fast as any toolbox method, because underneath all that toolbox code, it's still sockets that are used in the communication. So it makes sense that cutting out the middleman and using sockets directly would be faster. As for the third advantage, ease of implementation, you will soon see that implementing sockets classes in a Java program is very easy.
The Java source included with this article, testSocket, is a Java application using socket classes. A lot is going on here, but you wouldn't know it from the code. First, you need to declare the socket objects you are going to use. In my example, I've declared the socket object as ioSocket, the PrintWriter object as toServer, and the BufferReader object as fromServer. The socket object defines the host and port number; PrintWriter sends requests to the socket; and BufferReader receives information from the socket. Once the objects are declared, they are instantiated. The ioSocket object is set to a new socket with the TCP/IP address or host name of the server from which you are requesting information and to which the socket host code will run. The port number (3004, in this case) is the remote port that listens for the request, and the client uses any local port it can bind to. The toServer object instance of the PrintWriter class contains the request to the socket, and the fromServer object contains information received from the socket host. The fromServer object is constructed a little differently from testSocket and toServer, because Sun Microsystems recommends wrapping the InputStreamReader into BufferReader, for performance. Who am I to argue with Sun?
Next, you send the request to the socket and wait for a response. In my example, I am sending the string entered from the command line, when you run the Java application, to the socket host and waiting for a response, which I am storing in the string named temp. The fromServer object waits for the response before going to the next line of code that displays the response back to standard out, which in this case is the screen. The last thing to do in testSocket is to close the socket connections. I do this using the close() method from each object.
The Java Host Socket Class
Now let's take a look at the Java host socket class. It is part of the same source member, testSocket. MyHost is a separate class and not part of the socket client, but I've coded both the socket host and the socket client classes as part of testSocket.java. When you compile this Java code, you will create two classes: testSocket.class and myHost.class. You don't have to do it this way; I did it for simplicity. You could very easily separate them into their own source members, but what fun would that be? What's interesting about coding them in the same source member is that the two classes may run on different machines. (You'll have to excuse my excitement, but for an RPG-learning-Java programmer like me, this is pretty cool.)
OK, back to myHost. You first declare ServerSocket and socket classes, instantiating the ServerSocket class to port 3004. The accept method waits for a connection request from a client to the host and port of your server (in this example, port 3004). When you request and successfully establish a connection, the accept method returns a new socket object bound to a new local port. The server can then communicate with the client over this new socket and continue to listen for client connection requests on the ServerSocket bound to port 3004. After the request is accepted, it is read by using the readLine method, which returns the request to the clientData object. In my example, the request reads from the command line. The host then appends the string - Success to the clientData object and sends that string back to the client through a new port. Finish by closing the socket connections.
To run the client and have it communicate successfully with a host socket, you must first run the myHost class on the iSeries, or anywhere else you want to run it, but let's keep this iSeries-centric, shall we? Having said that, you will notice, in the Java example I sent you, that I used 127.0.0.1. This allowed me to run both the client and the host on my PC, but if you substitute that IP address with your iSeries IP address and run myHost on that iSeries, you'll be good to go. You can run myHost interactively by using the RUNJVA command from an OS/400 command line, or using the JAVA command in the Qshell environment. You can also submit the RUNJVA command to batch by using Submit Job (SBMJOB). If using the Java command from the Qshell, it would look like the following:
As soon as myHost is running on the AS/400, you can call your client from your DOS command line, using the JAVA command followed by the name of the class and the string you want to send to the host, like so:
Java testSocket Kevin
If all goes well, you should get a response on the screen that reads, "Kevin — Success."
You're Plugged In
I've shown you a very basic example of socket programming, but I think you'll see that using sockets with Java is not that difficult. Hey, I did it. You can also use sockets in RPG, but it is a tad more complex. I will provide an example of how to code sockets in an RPG program in the next issue. In that issue I will use the same socket client, but the host program will be written in RPG. You will then see how much more complex it is. What it will all mean is that you will have many alternatives to access RPG and DB2 on the iSeries. You can completely use the iSeries Java Toolbox; you can go "pure" java and use nothing but sockets, writing the clients in Java and the host in RPG; or you can mix and match the two technologies. Maybe it makes sense, because of the ease of coding sockets with Java, to code both the socket client and the host in Java, as I did in this article, and from the Java host, to employ the Java toolbox to get at the iSeries resources. The point is, there are many alternatives. Go mess around, but be sure to tune in for more good stuff.
Contact the Editors
Last Updated: 7/18/02
Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.