Java Newsletter by Glen McCluskey - Issue 12
Issue #012
December, 1996
Contents
- Jack
- Comparing C/C++ and Java Part 12 - Null
- JavaScript
- Introduction to Applet Programming Part 8 - Client/Server Example
- Correction
JACK
Lex and Yacc are widely-used tools for doing lexical scanning and parsing of input. You describe the structure of the input and these tools generate programs (in C) that will accept and structure such input. For example, an identifier might be lexically described as:
[a-zA-Z_][a-zA-Z_0-9]*
meaning that the identifier starts with a letter or underscore, followed by zero or more letters, underscores, or digits.
Similarly, a simple expression in BNF (Backus Naur Form) could look like:
E -> T | E + T
T -> F | T * F
F -> number | ( E )
This is known as a grammar, and programming languages like Java are formally described via a grammar. O'Reilly and others publish books on Lex/Yacc, if you want information on these tools.
Jack is a new tool that combines Lex and Yacc capabilities. It's written in Java and produces Java output, that is, produces Java programs for parsing input described via a grammar. Jack is available on the Web at:
You need the Java Development Kit 1.0.2 to use this program. With Jack you describe the lexical and syntactic structure of your program, and then have it produce Java programs that understand this structure.
As an example of a problem made simple by a tool of this type, consider the issue of extracting from Java programs basic information about what is defined where, for example, where a specific class or method is found in the source code. With Jack, it's simply a matter of dumping out key information whenever a particular construct like a method declaration is found.
For example, we might have this format for the output:
String.charAt method 204 java/src/java/lang/String.java
meaning that the charAt() method of class String is defined at line 204 of String.java.
An index produced in this format, representing all the classes, interfaces, methods, and constructors for JDK 1.0.2, is available via FTP at:
ftp://rmi.net/pub2/glenm/jack
along with a simple UNIX shell script browser to search and access any of the symbols in the database.
There are many other possibilities for the use of a tool of this type, for example test coverage or generation of class metrics. If you have interest in this area, please send me a note (glenm@glenmccl.com).
COMPARING C/C++ AND JAVA PART 12 - NULL
In C and C++, "NULL" is a constant defined in a header file, with a value like:
0
or:
0L
or:
((void*)0)
depending on the compiler and memory model options. NULL is not, strictly speaking, part of C/C++ itself.
In Java, "null" is not a keyword, but a special literal of the null type. It can be cast to any reference type, but not to any primitive type such as int or boolean. The null literal doesn't necessarily have value zero. And it is impossible to cast to the null type or declare a variable of this type.
JAVASCRIPT
You may have heard the term "JavaScript". What is its relation to Java and HTML? JavaScript started out as LiveScript and its connection to Java is fairly loose, sharing some Internet heritage but not that much else.
HTML (Hyper Text Markup Language) is not really a programming language in the usual sense of the term, but rather a language that describes what a page ought to look like. You can't really "do anything" with HTML.
Java is a general purpose programming language. One type of Java program, an applet, is downloadable by a Web browser and then executed locally by the browser. This is useful, for example, in communicating with remote databases. An applet's invocation is described via the HTML tags <applet> and </applet>.
JavaScript can be viewed as a language something like Perl, or as an extension of HTML to allow customized functionality. As an example of what a JavaScript application would look like, consider this example:
<html>
<body>
<a href="link1.html">Link #1</a>
<br>
<a href="link2.html">Link #2</a>
<br>
<script>
<!--
function doit()
{
document.write("<br>This page's links are:<br><br>");
for (var i = 0; i < document.links.length; i++) {
var s = "";
s += (i + 1) + ". ";
s += document.links[i];
s += "<br>";
document.write(s);
}
}
doit()
<!-- -->
</script>
</body>
<html>
This particular application iterates over the links in a page and displays them in a numbered list:
1. link1.html
2. link2.html
JavaScript as a programming language has a flavor something like Perl or Awk, with weak typing and domain-specific system variables like "document.links[]".
Note that the output of a JavaScript script is HTML, so for example we use "<br>" instead of "\n" to go to the next line. In the above example, the function doit() is defined, and then called to produce HTML.
We will probably not say more about JavaScript, but there are a variety of books available on the topic. You need a Web browser like Netscape 3.0 to execute JavaScript programs.
INTRODUCTION TO APPLET PROGRAMMING PART 8 - CLIENT/SERVER EXAMPLE
In this issue we'll show a simple example of client/server programming. The client will be an applet and the server a regular Java program with a main() method in it.
In the client/server model, there is a server program running on some computer. It accepts connections from clients across the network, and serves each of them. For example, the client may be used to accept some input from a user, which is sent to the server and entered into a database. The server can also send information back to the client, such as an acknowledgment.
Server and client communicate via what is known as a socket. More technically, a socket is an endpoint of a communications channel, and thus there is a socket on each end of the channel, one socket for the server and one for the client.
Given a socket, it's possible to do conventional Java I/O between server and client.
Let's now look at the programs:
// server.java
import java.io.*;
import java.net.*;
public class server extends Thread {
public static final int DEF_PORT = 1234;// port
private int port;
private ServerSocket listen; // server socket
public server()
{
// set up the server socket port
port = DEF_PORT;
try {
listen = new ServerSocket(port);
}
catch (IOException e) {
System.err.println("socket creation error");
System.exit(1);
}
// start the server thread running
start();
}
public void run()
{
try {
// accept connections and process them
for (;;) {
Socket cs = listen.accept();
connection c = new connection(cs);
}
}
catch (IOException e) {
System.err.println("connection error");
}
}
public static void main(String[] args)
{
new server();
}
}
class connection extends Thread {
private Socket client; // client socket
private DataInputStream in; // input from socket
private PrintStream out; // output to socket
public connection(Socket cs)
{
// set up an individual connection
try {
client = cs;
InputStream is = client.getInputStream();
in = new DataInputStream(is);
OutputStream os = client.getOutputStream();
out = new PrintStream(os);
}
catch (IOException e) {
try {
client.close();
}
catch (IOException ee) {
System.err.println("close error");
}
System.err.println("socket stream error");
return;
}
// start it running
start();
}
public void run()
{
// read from socket input and write back to output
try {
for (;;) {
String ln = in.readLine();
if (ln == null)
break;
if (ln.length() == 0)
out.println("empty input");
else
out.println("OK: " + ln);
}
}
catch (IOException e) {
System.err.println("server I/O error");
}
// close connection
finally {
try {
client.close();
}
catch (IOException ee) {
System.err.println("close error");
}
}
}
}
// client.java
import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
public class client extends Applet {
public static final int DEF_PORT = 1234;// port
Socket s; // socket
DataInputStream in; // socket input
private PrintStream out; // socket output
TextField input_field; // input field
TextArea out_area; // output display area
public void init()
{
try {
// set up socket
String host = getCodeBase().getHost();
s = new Socket(host, DEF_PORT);
in = new DataInputStream(s.getInputStream());
out = new PrintStream(s.getOutputStream());
// set up window
input_field = new TextField();
out_area = new TextArea();
out_area.setEditable(false);
setLayout(new BorderLayout());
add("North", input_field);
add("Center", out_area);
}
catch (IOException e) {
System.err.println("exception during setup");
}
}
public boolean action(Event e, Object o)
{
if (e.target == input_field) {
// we have some input from the user
try {
// dump it to the server
out.println((String)e.arg);
input_field.setText("");
// read response
String status = in.readLine();
out_area.setText(status);
return true;
}
catch (IOException ee) {
out_area.setText("server I/O error");
}
}
return false;
}
}
The server is compiled as usual and simply started as a Java program:
$ java server
while the client is driven via some HTML:
<html>
<head>
<title>Client Applet</title>
</head>
<body>
<applet code="client.class" width=300 height=300></applet>
</body>
</html>
If you start the client without the server being present, it will give an error because of failure to connect to the server.
This particular server/client combination simply validates input from the client and sends back an acknowledgment. Each client connection runs as a separate thread, so that many clients can be served simultaneously without the need for polling.
Note that the server knows to close a given client connection (the client has gone away) by receipt of a "null" when reading input from that connection. By contrast, the server "never" goes away; it must be explicitly terminated by the user.
Note also that the socket port must be unique on the system running the server, and that the server and client must agree on port assignments.
CORRECTION
In issue #011 we presented an example of animation. Steve Drach pointed out that a call to dispose() is needed, as follows:
// run a thread
public void run()
{
for (;;) {
// get graphics for the applet window
Graphics g = this.getGraphics();
try {
switch (st++) {
case 0:
g.setColor(Color.red);
g.fillOval(25, 35, 250, 250);
break;
// other switch cases ...
}
// sleep for a second
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
g.dispose(); // <<<<<<<<<<<<<<<<<<<<
}
}
Without this, the animation will eventually stall out. This is different from garbage collection, which is automatic, and involves freeing of windows resources. That is, getGraphics() retrieves one of a limited number of system window resources, which must be returned via dispose(). A similar case might come up when dealing with a resource such as UNIX file descriptors.
ACKNOWLEDGEMENTS
Thanks to Jay Burgess, Thierry Ciot, Irv Kanode, Mike McCann, Mike Paluka, Srihari Sampathkumar, and Bob Shore for help with proofreading.
SUBSCRIPTION INFORMATION / BACK ISSUES
To subscribe to the newsletter, send mail to majordomo@world.std.com with this line as its message body:
subscribe java_letter
Back issues are available via FTP from:
rmi.net /pub2/glenm/javalett
or on the Web at:
There is also a C++ newsletter. To subscribe to it, say:
subscribe c_plus_plus
using the same majordomo@world.std.com address.
-------------------------
Copyright (c) 1996 Glen McCluskey. All Rights Reserved.
This newsletter may be further distributed provided that it is copied in its entirety, including the newsletter number at the top and the copyright and contact information at the bottom.
Glen McCluskey & Associates
Professional Computer Consulting
Internet: glenm@glenmccl.com
Phone: (800) 722-1613 or (970) 490-2462
Fax: (970) 490-2463
FTP: rmi.net /pub2/glenm/javalett (for back issues)
Web: http://rainbow.rmi.net/~glenm