Sei sulla pagina 1di 78

UNIT 1

Java Introduction:
Java Programming Language was designed by James Gosling at Sun Microsystems in 1991. This language was initially called Oak but was renamed as Java in 1995. It follows both the C and C++ features. Java programming language was very useful on Internet Programming. Since, by using this language we can easily transfer the information from server to the nodes through the network. Generally, In the case of network programs security and portability is the main active areas of concern. The java programs are classified into An Application is a program run on the computer under the operating system of the computer. An Applet is an application designed to be transmitted over the Internet and executed by a java-compatible web browser.

Buzz Words:
a) Platform Independent: Java is a platform independent language. Once we create the program in one operating system, that program will be worked on any other operating system that is transmitted to the operating system. b) Portable: The most significant contribution of java over other languages is its portability. c) Object Oriented: java is a true object oriented language. Why because with out class we cant run the program. d) Robust & Secure: java is a Robust Language. It provides many safe guards to ensure reliable code. It designed as garbage collected language reliving the programmers, virtually all memory management problems. e) Distributed: Java is designed as distributed language for creating applications on network. It has the ability to share both data and program. f) g) h) Simple & Small : Java is simple & small language. Many features of C and C++ that are sources are unreliable code are not part of Java. Multi Threaded : Java was designed to meet the real-world requirement of creating interactive, networked programs. Java supports multithreaded programming, which allows to handling multi tasks simultaneously. Dynamic : Java is a dynamic language. Java is capable on dynamically linking in new class, libraries, methods and objects. Java supports functions written in other languages such as C and C++.

i) j)

Compile & Interpreted : Usually a Computer language is either compiled or interpreted. Java combined both these approaches thus making. Java is a two-stage system. High performance : Java performance is impressing for an interpreted language due to the use of intermediate code.

Basics of JAVA Environment : Phase 1 Java program is type in a text editor(notepad, Edit plus) and maked corrections if necessary. Phase 2 The programmer gives the command javac filename.java to compile the program. Phase 3 This phase is called loading. The program must place in memory before it can be executed. Phase 4 Byte code verifier confirms that all byte codes are valid and dont valid the Java Security Instructions. Phase 5 Java Interpreter reads byte code and translates them into a language that the computer can understand and it can executes the code. Java Development Kit Syntax : javac filename.java Syntax : java filename Syntax : jdb filename Servletrunner : A simple web server to test servels Syntax : appletviewer filename.html Java Virtual Machine(JVM) Java provides both compiler and a software machine called JVM for each computer machine. The Java compiler translates the java source code into a intermediate code known as byte code. Just In time(JIT) The Java Virtual Machine is an interpreter that translates and runs each bytecode instruction separately whenever it is needed by the computer program. Java Standard Libray(JSL) The Java API is a collection of classes and methods grouped in the form of packages. The important packages in Java are a) java.lang b) java.util c) java.io d) java.awt e) java.applet

f) javax.swing Difference between C++ and Java 1. Java does not include structure and union 2. It is not possible to declare unsigned interger in Java. 3. Pointers dont exist in java 4. Java does not have a preprocessor.

UNIT-2
Java Tokens: Tokens are smallest individual units in a program. The compiler reads the source program one character at a time grouping the source program into a sequence of atomic units called Tokens. Keywords : The keywords or Reserved words are one which have a special and predefined meaning to the Java compiler. The reserved words currently used in java are Abstract Boolean break byte case catch Char class const continue default do Double else extends final finally float For goto if implements import Datatype Datatypes are used to specify the type of data that a variable can attain. There are 2 type of datatypes. 1. Primitive 2. Non-primitive 1. Primitive Datatype : It is also called as standard, intrinsic or built in datatypes. There are eight primitive datatypes available in java. Those are byte, short int, long, char, float, double and Boolean. These can be classified into 4 groups. Integers : byte, short, int,long Floating point numbers : float, double Character s : char Boolean : Boolean 2. Non- primitive datatype : These are known as Derived Datatype or Abstract datatype or Reference type. These are built on primitive data types. Example : string, class, array Variable : The name given to the various elements to store the information is called an identifier or variable. The rules are Variable must be begin with a letter , a dollar($) symbol or an underscore(_) followed by a sequence of letters. Variable names must be unique. Declaring a variable : All variables must be declared before they can be used . The basic form of a variable declaration is Syntax : type identifier Where type represents datatype of the variable, identifier is the name of the variable. More than one variable of the same type can be declared by using a comma-separated list. Syntax : type identifier 1, identifier 2 identifier n

Intiliazing a variable: variable can also be intiliazed with equal sign and a value. Syntax : type identifier = value. Scope & Life time of a variable : An identifier duration also called lifetime is the period during which that identifier exist in memory. Identifer that represent local variables in a method i.e., parameters and variables declared in the methods body have automatic duration. Class : A class is a non-primitive datatype that contains member variables and member functions that operates on the variables. A class is declared by the use of the class keyword. Object : Object is an instance of the class. By means of the object only. We can access the functionhs(methods) Comments in a program : Three types of comments are available in java. i) Single line comment(//) : For Single line comment we use double slash(//). ii) Multi line comment : For more that one line of information we use multi line comments. They starts with /* and ends with */ iii) Documentation comment : For the documentation purpose we use. They starts with /** and ends with */. Input and Output Statements : Java.lang packages consists a class called system which contains console I/O. methods. If we want to take the information form the keyboard and display the information on the screen, Java uses Stream objects. Those are a) System.in b) System.out c) System.err Operators Operator is a symbol that performs a speicified operation between the data items. Java provides different types of operators a) Arithmetic operators : + addition substraction * Multiplication / Division b) Arithmetic Assignment Operators : Syntax : variable operator = expression Which is equivalent to

Variable = variable operator expression += a+=4 a=a+4 -= a-=5 a=a-5 Assignment operator : = is an assignment operator used to assign the value to a variable. Syntax : variable = value Increment and Decrement Operators : ++ and - - are Javas increment and decrement operators. The increment operator increased its operand by one. CLASS & OBJECTS Class : A Class is a non-primitive datatype that contains member variables (data) and member functions (methods) that operates on the variables. A class is declared by the use of the class keyword. Creating Objects An object in Java is a block of memory that contains space to store all the instance variables. Creating an object of a class is a two-step process. 1. Declare a variable of the class type. At this stage, the variable refers to an object only. 2. Assigning an actual, physical copy of the object and assign it to that variable by means of new operator. Methods : Methods allows the programmer to modularize a program. All variables declared in method definition are local variables and method parameters are also local variables. Method Overloading : In Java it is possible to define two or more methods within the same class that share the same name as long as these methods have different set of parameters(Based on the number of parameters, the type of the parameters and the order of the parameters). Then the methods are said to be overloaded, and the process is referred as Method Overloading. Constructors A constructor is a special method of class, which is invoked automatically, whenever an object of a class is created. A constructor has the following characteristics It doesnt have any return type not even void. The constructor can be declared as public It can be overloaded D

Default constructor : A constructor that accepts no parameters is called the default constructor. Parameterized constructor : A constructor that takes arguments as parameters is called parameterized constructor. Constructor Overloading : An interesting feature of the constructor is that a class can have multiple constructors. This is called constructor overloading. Static Class Members Generally each class contains instance variables and instance methods. Every time the class is instantiated, a new copy of each of them is created. They are accessed using the objects with the dot operator. this keyword Java define this keyword that can be used inside and method to refer the current object. this is always a reference to the object on which methods was invoked. Argument Passing : Arguments passed to a sub-routine(method) is falls into 2 categories 1. Call by value 2. Call by reference 1. Call by value : Call by value copies the value of an argument into the formal parameter of the sub-routine. 2. Call by reference : In this method, a reference to an argument is passed to the parameter. Inside the parameter, this reference is used to access the actual argument specified in the call. Strings : A String is a collection of characters. Java implements strings as object type of string. Java properties 3 types of string handling classes. 1. String class 2. StringBuffer Class 3. StringTokenizer Class String and StringBuffer classes are defined in java.lang package. StringTokenizer are defined in java.util package. String Class : A String is an object of class String. String literals or constants written as a sequence of characters in double quotes.

StringBuffer Class : Once a String object is created then its contents cannot be changed. But the StringBuffer class provides the features of creating and manipulating dynamic string information i.e., mutable strings. StringBuffer Constructors : a) StringBuffer() : It is a default StringBuffer Constructor to create StringBuffer with no characters init and an initial capacity of 16 characters. b) StringBuffer(String str) : It takes a String argument to create a StringBuffer containing the characters of the String argument. The Initial capacity is the number of arguments in the string argument +16. c) StringBuffer(int size) : It takes an integer argument and creates a StringBuffer with no characters init. The intial capacity is specified bythe integer. StringTokenizer Class : In programming languages, statements are divided into individual pieces like identifers, keywords, and operators etc., called Tokens Java provides StringTokenizer class that breaks a String into its component tokens. StringTokenizer Constructors : a) StringTokenizer(String str) b) StringTokenizer (String str, String delimiters) c) StringTokenizer(String str, String delimiters, Boolean delimiterAsToken)

UNIT-3 Inheritance
The mechanism of deriving a new class from an old one is called Inheritance. A class that is inherited (old class) is called a super class or base class or parent class.

Types of Inheritances
Inheritance is classified into different forms. a) single Inheritance : Derivation a subclass from only one super class is called single Inheritance. b) Hierarchical Inheritance : Derivation of several classes from a single super class is called Hierarchical Inheritance. c) Multilevel Inheritance : Derivation of a class from another derived class called multilevel Inheritance. d) Multiple Inheritance : Derivation of one class from two or more super classes is called Multiple Inheritance. e) Hybrid Inheritance: Derivation of a class involving more than one form of Inheritance is called Hybrid Inheritance. Defining a Sub class. A subclass is defined as Syntax : class subclass-name extends superclass-name { Variable declaration Method declaration } Member Access Rules : 1. By means of sub class object it is possible to access all the instance variables and instance methods of the super class. 2. By means of sub class object it cannot be possible to access the instance variable of super class, if it is declared as private. Since the data is protected in that class. Super keyword : A subclass constructor is used to construct the instance variable of both the subclass and the super class. The subclass constructor uses the keyword super to invoke the constructor method of the super class. The keyword super is used subject to the following conditions. Super may be used only within the subclass constructor method. The call to super class constructor must appear as the first statement with in the subclass constructor. If a parameterized constructor is used, then the signature is matched with the parameters passed to the super method as super(parameter-list)

Method Overriding A method in a subclass has the same name, type of the variables and order of the variables as method in its super class, then the method in the subclass is said to be override the method in the super class. The process is called Method Overriding. Note : Method Overriding occurs only when the name and type signature of the two methods are identical. If method name is identical and the type signature is different then the process is said to be Method Overloading. Final Keyword A final is a keyword used for three purposes. They are a) final as constant : A variable can be decalred as constant with the keyword final. b) Final to prevent overriding : A Method that is declared as final cannot be overridden in a subclass method. c) Final to prevent inheritance : The class that is declared as final implicitly declares all of its methods as final. Object Class Java provides a special class called Object class that is available in java.lang package. It is the super class of all other classes. Method Object clone() Boolean equals(Object object) Void finalize() Class getClass() Int hascode() Purpose creates a new object that is the same as the object being cloned. Determines whether one object is equal to another Called before an unused object is recycled. Obtains the class of an object at run time. Returns the has code associated with the invoking object.

Dynamic Method Dispatch : Dynamic Method Dispatch is the mechanism by which a class to an overridden method is resolved at runtime, rather than compile time. Dynamic method dispatch is important because this is how Java implements run-time polymorphism.

UNIT 4
Creating and Using Packages To make types easier to find and use, to avoid naming conflicts, and to control access, programmers bundle groups of related types into packages. Definition: A package is a grouping of related types providing access protection and name space management. Note that types refers to classes, interfaces, enumerations, and annotation types. Enumerations and annotation types are special kinds of classes and interfaces, respectively, so types are often referred to in this lesson simply as classes and interfaces. The types that are part of the Java platform are members of various packages that bundle classes by function: fundamental classes are in java.lang, classes for reading and writing (input and output) are in java.io, and so on. You can put your types in packages too. Suppose you write a group of classes that represent graphic objects, such as circles, rectangles, lines, and points. You also write an interface, Draggable, that classes implement if they can be dragged with the mouse. //in the Draggable.java file public interface Draggable { ... } //in the Graphic.java file public abstract class Graphic { ... } //in the Circle.java file public class Circle extends Graphic implements Draggable { ... } //in the Rectangle.java file public class Rectangle extends Graphic implements Draggable { ... } //in the Point.java file public class Point extends Graphic implements Draggable { ... } //in the Line.java file public class Line extends Graphic implements Draggable {

... } You should bundle these classes and the interface in a package for several reasons, including the following:

You and other programmers can easily determine that these types are related. You and other programmers know where to find types that can provide graphicsrelated functions. The names of your types won't conflict with the type names in other packages because the package creates a new namespace. You can allow types within the package to have unrestricted access to one another yet still restrict access for types outside the package.

Creating a Package To create a package, you choose a name for the package (naming conventions are discussed in the next section) and put a package statement with that name at the top of every source file that contains the types (classes, interfaces, enumerations, and annotation types) that you want to include in the package. The package statement (for example, package graphics;) must be the first line in the source file. There can be only one package statement in each source file, and it applies to all types in the file. Note: If you put multiple types in a single source file, only one can be public, and it must have the same name as the source file. For example, you can define public class Circle in the file Circle.java, define public interface Draggable in the file Draggable.java, define public enum Day in the file Day.java, and so forth. You can include non-public types in the same file as a public type (this is strongly discouraged, unless the non-public types are small and closely related to the public type), but only the public type will be accessible from outside of the package. All the top-level, non-public types will be package private. If you put the graphics interface and classes listed in the preceding section in a package called graphics, you would need six source files, like this: //in the Draggable.java file package graphics; public interface Draggable { ... } //in the Graphic.java file package graphics; public abstract class Graphic { ...

} //in the Circle.java file package graphics; public class Circle extends Graphic implements Draggable { ... } //in the Rectangle.java file package graphics; public class Rectangle extends Graphic implements Draggable { ... } //in the Point.java file package graphics; public class Point extends Graphic implements Draggable { ... } //in the Line.java file package graphics; public class Line extends Graphic implements Draggable { ... } If you do not use a package statement, your type ends up in an unnamed package. Generally speaking, an unnamed package is only for small or temporary applications or when you are just beginning the development process. Otherwise, classes and interfaces belong in named packages. Naming a Package With programmers worldwide writing classes and interfaces using the Java programming language, it is likely that many programmers will use the same name for different types. In fact, the previous example does just that: It defines a Rectangle class when there is already a Rectangle class in the java.awt package. Still, the compiler allows both classes to have the same name if they are in different packages. The fully qualified name of each Rectangle class includes the package name. That is, the fully qualified name of the Rectangle class in the graphics package is graphics.Rectangle, and the fully qualified name of the Rectangle class in the java.awt package is java.awt.Rectangle. This works well unless two independent programmers use the same name for their packages. What prevents this problem? Convention. Naming Conventions Package names are written in all lowercase to avoid conflict with the names of classes or interfaces.

Companies use their reversed Internet domain name to begin their package namesfor example, com.example.orion for a package named orion created by a programmer at example.com. Name collisions that occur within a single company need to be handled by convention within that company, perhaps by including the region or the project name after the company name (for example, com.company.region.package). Packages in the Java language itself begin with java. or javax. In some cases, the internet domain name may not be a valid package name. This can occur if the domain name contains a hyphen or other special character, if the package name begins with a digit or other character that is illegal to use as the beginning of a Java name, or if the package name contains a reserved Java keyword, such as "int". In this event, the suggested convention is to add an underscore. For example: Legalizing Package Names Domain Name Package Name Prefix clipart-open.org org.clipart_open free.fonts.int int_.fonts.free poetry.7days.com com._7days.poetry Using Package Members The types that comprise a package are known as the package members. To use a public package member from outside its package, you must do one of the following:

Refer to the member by its fully qualified name Import the package member Import the member's entire package

Each is appropriate for different situations, as explained in the sections that follow. Referring to a Package Member by Its Qualified Name So far, most of the examples in this tutorial have referred to types by their simple names, such as Rectangle and StackOfInts. You can use a package member's simple name if the code you are writing is in the same package as that member or if that member has been imported. However, if you are trying to use a member from a different package and that package has not been imported, you must use the member's fully qualified name, which includes the package name. Here is the fully qualified name for the Rectangle class declared in the graphics package in the previous example.

graphics.Rectangle You could use this qualified name to create an instance of graphics.Rectangle: graphics.Rectangle myRect = new graphics.Rectangle(); Qualified names are all right for infrequent use. When a name is used repetitively, however, typing the name repeatedly becomes tedious and the code becomes difficult to read. As an alternative, you can import the member or its package and then use its simple name. Importing a Package Member To import a specific member into the current file, put an import statement at the beginning of the file before any type definitions but after the package statement, if there is one. Here's how you would import the Rectangle class from the graphics package created in the previous section. import graphics.Rectangle; Now you can refer to the Rectangle class by its simple name. Rectangle myRectangle = new Rectangle(); This approach works well if you use just a few members from the graphics package. But if you use many types from a package, you should import the entire package. Importing an Entire Package To import all the types contained in a particular package, use the import statement with the asterisk (*) wildcard character. import graphics.*; Now you can refer to any class or interface in the graphics package by its simple name. Circle myCircle = new Circle(); Rectangle myRectangle = new Rectangle(); The asterisk in the import statement can be used only to specify all the classes within a package, as shown here. It cannot be used to match a subset of the classes in a package. For example, the following does not match all the classes in the graphics package that begin with A. import graphics.A*; //does not work Instead, it generates a compiler error. With the import statement, you generally import only a single package member or an entire package. Note: Another, less common form of import allows you to import the public nested classes of an enclosing class. For example, if the graphics.Rectangle class contained useful nested classes, such as Rectangle.DoubleWide and Rectangle.Square, you could import Rectangle and its nested classes by using the following two statements. import graphics.Rectangle; import graphics.Rectangle.*; Be aware that the second import statement will not import Rectangle. Another less common form of import, the static import statement, will be discussed at the end of this section.

For convenience, the Java compiler automatically imports three entire packages for each source file: (1) the package with no name, (2) the java.lang package, and (3) the current package (the package for the current file). Apparent Hierarchies of Packages At first, packages appear to be hierarchical, but they are not. For example, the Java API includes a java.awt package, a java.awt.color package, a java.awt.font package, and many others that begin with java.awt. However, the java.awt.color package, the java.awt.font package, and other java.awt.xxxx packages are not included in the java.awt package. The prefix java.awt (the Java Abstract Window Toolkit) is used for a number of related packages to make the relationship evident, but not to show inclusion. Importing java.awt.* imports all of the types in the java.awt package, but it does not import java.awt.color, java.awt.font, or any other java.awt.xxxx packages. If you plan to use the classes and other types in java.awt.color as well as those in java.awt, you must import both packages with all their files: import java.awt.*; import java.awt.color.*; Summary of Creating and Using Packages To create a package for a type, put a package statement as the first statement in the source file that contains the type (class, interface, enumeration, or annotation type). To use a public type that's in a different package, you have three choices: (1) use the fully qualified name of the type, (2) import the type, or (3) import the entire package of which the type is a member. The path names for a package's source and class files mirror the name of the package. You might have to set your CLASSPATH so that the compiler and the JVM can find the .class files for your types. Implementing Interfaces Once an Interface has been defined, one or more classes can implement that interface. implements keyword used for implementing the classes. The syntax of implements is as follows. Syntax : class class-name implements interface 1, interface 2 , interface n { // interface body }

Note : 1. Interface methods are similar to the abstract classes so, that it cannot be instantiated. 3. Interface methods can also be accessed by the interface reference variable refer to the object of subclass. The method will be resolved at run time. This process is similar to the super class reference to access a subclass object

UNIT 5
What Is an Exception?
The term exception is shorthand for the phrase "exceptional event." Definition: An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception. After a method throws an exception, the runtime system attempts to find something to handle it. The set of possible "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack (see the next figure).

The call stack. The runtime system searches the call stack for a method that contains a block of code that can handle the exception. This block of code is called an exception handler. The search begins with the method in which the error occurred and proceeds through the call stack in the reverse order in which the methods were called. When an appropriate handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type that can be handled by the handler. The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all the methods on the call stack without finding an appropriate exception handler, as shown in the next figure, the runtime system (and, consequently, the program) terminates.

Searching the call stack for the exception handler. Using exceptions to manage errors has some advantages over traditional errormanagement techniques. You can learn more in the Advantages of Exceptions section. The Catch or Specify Requirement Valid Java programming language code must honor the Catch or Specify Requirement. This means that code that might throw certain exceptions must be enclosed by either of the following:

A try statement that catches the exception. The try must provide a handler for the exception, as described in Catching and Handling Exceptions. A method that specifies that it can throw the exception. The method must provide a throws clause that lists the exception, as described in Specifying the Exceptions Thrown by a Method.

Code that fails to honor the Catch or Specify Requirement will not compile. Not all exceptions are subject to the Catch or Specify Requirement. To understand why, we need to look at the three basic categories of exceptions, only one of which is subject to the Requirement. The Three Kinds of Exceptions The first kind of exception is the checked exception. These are exceptional conditions that a well-written application should anticipate and recover from. For example, suppose an application prompts a user for an input file name, then opens the file by passing the name to the constructor for java.io.FileReader. Normally, the user provides the name of an existing, readable file, so the construction of the FileReader object succeeds, and the execution of the application proceeds normally. But sometimes the user supplies the name of a nonexistent file, and the constructor throws java.io.FileNotFoundException. A

well-written program will catch this exception and notify the user of the mistake, possibly prompting for a corrected file name. Checked exceptions are subject to the Catch or Specify Requirement. All exceptions are checked exceptions, except for those indicated by Error, RuntimeException, and their subclasses. The second kind of exception is the error. These are exceptional conditions that are external to the application, and that the application usually cannot anticipate or recover from. For example, suppose that an application successfully opens a file for input, but is unable to read the file because of a hardware or system malfunction. The unsuccessful read will throw java.io.IOError. An application might choose to catch this exception, in order to notify the user of the problem but it also might make sense for the program to print a stack trace and exit. Errors are not subject to the Catch or Specify Requirement. Errors are those exceptions indicated by Error and its subclasses. The third kind of exception is the runtime exception. These are exceptional conditions that are internal to the application, and that the application usually cannot anticipate or recover from. These usually indicate programming bugs, such as logic errors or improper use of an API. For example, consider the application described previously that passes a file name to the constructor for FileReader. If a logic error causes a null to be passed to the constructor, the constructor will throw NullPointerException. The application can catch this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur. Runtime exceptions are not subject to the Catch or Specify Requirement. Runtime exceptions are those indicated by RuntimeException and its subclasses. Errors and runtime exceptions are collectively known as unchecked exceptions. Bypassing Catch or Specify Some programmers consider the Catch or Specify Requirement a serious flaw in the exception mechanism and bypass it by using unchecked exceptions in place of checked exceptions. In general, this is not recommended. The section Unchecked Exceptions The Controversy talks about when it is appropriate to use unchecked exceptions. Catching and Handling Exceptions This section describes how to use the three exception handler components the try, catch, and finally blocks to write an exception handler. The last part of this section walks through an example and analyzes what occurs during various scenarios. The following example defines and implements a class named ListOfNumbers. When constructed, ListOfNumbers creates a Vector that contains 10 Integer elements with

sequential values 0 through 9. The ListOfNumbers class also defines a method named writeList, which writes the list of numbers into a text file called OutFile.txt. This example uses output classes defined in java.io, which are covered in Basic I/O. //Note: This class won't compile by design! import java.io.*; import java.util.Vector; public class ListOfNumbers { private Vector vector; private static final int SIZE = 10; public ListOfNumbers () { vector = new Vector(SIZE); for (int i = 0; i < SIZE; i++) { vector.addElement(new Integer(i)); } } public void writeList() { PrintWriter out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) { out.println("Value at: " + i + " = " + vector.elementAt(i)); } out.close(); } } The first line in boldface is a call to a constructor. The constructor initializes an output stream on a file. If the file cannot be opened, the constructor throws an IOException. The second boldface line is a call to the Vector class's elementAt method, which throws an ArrayIndexOutOfBoundsException if the value of its argument is too small (less than 0) or too large (more than the number of elements currently contained by the Vector). If you try to compile the ListOfNumbers class, the compiler prints an error message about the exception thrown by the FileWriter constructor. However, it does not display an error message about the exception thrown by elementAt. The reason is that the exception thrown by the constructor, IOException, is a checked exception, and the one thrown by the elementAt method, ArrayIndexOutOfBoundsException, is an unchecked exception.

Now that you're familiar with the ListOfNumbers class and where the exceptions can be thrown within it, you're ready to write exception handlers to catch and handle those exceptions. The try Block The first step in constructing an exception handler is to enclose the code that might throw an exception within a try block. In general, a try block looks like the following. try { code } catch and finally blocks . . . The segment in the example labeled code contains one or more legal lines of code that could throw an exception. (The catch and finally blocks are explained in the next two subsections.) To construct an exception handler for the writeList method from the ListOfNumbers class, enclose the exception-throwing statements of the writeList method within a try block. There is more than one way to do this. You can put each line of code that might throw an exception within its own try block and provide separate exception handlers for each. Or, you can put all the writeList code within a single try block and associate multiple handlers with it. The following listing uses one try block for the entire method because the code in question is very short. private Vector vector; private static final int SIZE = 10; PrintWriter out = null; try { System.out.println("Entered try statement"); out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) { out.println("Value at: " + i + " = " + vector.elementAt(i)); } } catch and finally statements . . . If an exception occurs within the try block, that exception is handled by an exception handler associated with it. To associate an exception handler with a try block, you must put a catch block after it; the next section shows you how. The catch Blocks You associate exception handlers with a try block by providing one or more catch blocks directly after the try block. No code can be between the end of the try block and the beginning of the first catch block.

try { } catch (ExceptionType name) { } catch (ExceptionType name) { } Each catch block is an exception handler and handles the type of exception indicated by its argument. The argument type, ExceptionType, declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name. The catch block contains code that is executed if and when the exception handler is invoked. The runtime system invokes the exception handler when the handler is the first one in the call stack whose ExceptionType matches the type of the exception thrown. The system considers it a match if the thrown object can legally be assigned to the exception handler's argument. The following are two exception handlers for the writeList method one for two types of checked exceptions that can be thrown within the try statement. try { } catch (FileNotFoundException e) { System.err.println("FileNotFoundException: " + e.getMessage()); throw new SampleException(e); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } Both handlers print an error message. The second handler does nothing else. By catching any IOException that's not caught by the first handler, it allows the program to continue executing. The first handler, in addition to printing a message, throws a user-defined exception. (Throwing exceptions is covered in detail later in this chapter in the How to Throw Exceptions section.) In this example, when the FileNotFoundException is caught it causes a user-defined exception called SampleException to be thrown. You might want to do this if you want your program to handle an exception in this situation in a specific way. Exception handlers can do more than just print error messages or halt the program. They can do error recovery, prompt the user to make a decision, or propagate the error up to a

higher-level handler using chained exceptions, as described in the Chained Exceptions section. The finally Block The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated. Note: If the JVM exits while the try or catch code is being executed, then the finally block will not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block will not execute even though the application as a whole continues. The try block of the writeList method that you've been working with here opens a PrintWriter. The program should close that stream before exiting the writeList method. This poses a somewhat complicated problem because writeList's try block can exit in one of three ways. 1. The new FileWriter statement fails and throws an IOException. 2. The vector.elementAt(i) statement fails and throws an ArrayIndexOutOfBoundsException. 3. Everything succeeds and the try block exits normally. The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup. The following finally block for the writeList method cleans up and then closes the PrintWriter. finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } } In the writeList example, you could provide for cleanup without the intervention of a finally block. For example, you could put the code to close the PrintWriter at the end of the try block and again within the exception handler for ArrayIndexOutOfBoundsException, as follows. try {

out.close();

//Don't do this; it duplicates code.

} catch (FileNotFoundException e) { out.close(); //Don't do this; it duplicates code. System.err.println("Caught: FileNotFoundException: " + e.getMessage()); throw new RuntimeException(e); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } However, this duplicates code, thus making the code difficult to read and error-prone should you modify it later. For example, if you add code that can throw a new type of exception to the try block, you have to remember to close the PrintWriter within the new exception handler. Important: The finally block is a key tool for preventing resource leaks. When closing a file or otherwise recovering resources, place the code in a finally block to insure that resource is always recovered. Putting It All Together The previous sections described how to construct the try, catch, and finally code blocks for the writeList method in the ListOfNumbers class. Now, let's walk through the code and investigate what can happen. When all the components are put together, the writeList method looks like the following. public void writeList() { PrintWriter out = null; try { System.out.println("Entering try statement"); out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) out.println("Value at: " + i + " = " + vector.elementAt(i)); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught " + "ArrayIndexOutOfBoundsException: " + e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage());

} finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } } } As mentioned previously, this method's try block has three different exit possibilities; here are two of them. 1. Code in the try statement fails and throws an exception. This could be an IOException caused by the new FileWriter statement or an ArrayIndexOutOfBoundsException caused by a wrong index value in the for loop. 2. Everything succeeds and the try statement exits normally. Let's look at what happens in the writeList method during these two exit possibilities. Scenario 1: An Exception Occurs The statement that creates a FileWriter can fail for a number of reasons. For example, the constructor for the FileWriter throws an IOException if the program cannot create or write to the file indicated. When FileWriter throws an IOException, the runtime system immediately stops executing the try block; method calls being executed are not completed. The runtime system then starts searching at the top of the method call stack for an appropriate exception handler. In this example, when the IOException occurs, the FileWriter constructor is at the top of the call stack. However, the FileWriter constructor doesn't have an appropriate exception handler, so the runtime system checks the next method the writeList method in the method call stack. The writeList method has two exception handlers: one for IOException and one for ArrayIndexOutOfBoundsException. The runtime system checks writeList's handlers in the order in which they appear after the try statement. The argument to the first exception handler is ArrayIndexOutOfBoundsException. This does not match the type of exception thrown, so the runtime system checks the next exception handler IOException. This matches the type of exception that was thrown, so the runtime system ends its search for an appropriate exception handler. Now that the runtime has found an appropriate handler, the code in that catch block is executed.

After the exception handler executes, the runtime system passes control to the finally block. Code in the finally block executes regardless of the exception caught above it. In this scenario, the FileWriter was never opened and doesn't need to be closed. After the finally block finishes executing, the program continues with the first statement after the finally block. Here's the complete output from the ListOfNumbers program that appears when an IOException is thrown. Entering try statement Caught IOException: OutFile.txt PrintWriter not open The boldface code in the following listing shows the statements that get executed during this scenario: public void writeList() { PrintWriter out = null; try { System.out.println("Entering try statement"); out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) out.println("Value at: " + i + " = " + vector.elementAt(i)); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught " + "ArrayIndexOutOfBoundsException: " + e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } } } Scenario 2: The try Block Exits Normally

In this scenario, all the statements within the scope of the try block execute successfully and throw no exceptions. Execution falls off the end of the try block, and the runtime system passes control to the finally block. Because everything was successful, the PrintWriter is open when control reaches the finally block, which closes the PrintWriter. Again, after the finally block finishes executing, the program continues with the first statement after the finally block. Here is the output from the ListOfNumbers program when no exceptions are thrown. Entering try statement Closing PrintWriter The boldface code in the following sample shows the statements that get executed during this scenario. public void writeList() { PrintWriter out = null; try { System.out.println("Entering try statement"); out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) out.println("Value at: " + i + " = " + vector.elementAt(i)); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught " + "ArrayIndexOutOfBoundsException: " + e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } } } Processes and Threads

In concurrent programming, there are two basic units of execution: processes and threads. In the Java programming language, concurrent programming is mostly concerned with threads. However, processes are also important. A computer system normally has many active processes and threads. This is true even in systems that only have a single execution core, and thus only have one thread actually executing at any given moment. Processing time for a single core is shared among processes and threads through an OS feature called time slicing. It's becoming more and more common for computer systems to have multiple processors or processors with multiple execution cores. This greatly enhances a system's capacity for concurrent execution of processes and threads but concurrency is possible even on simple systems, without multiple processors or execution cores. Processes A process has a self-contained execution environment. A process generally has a complete, private set of basic run-time resources; in particular, each process has its own memory space. Processes are often seen as synonymous with programs or applications. However, what the user sees as a single application may in fact be a set of cooperating processes. To facilitate communication between processes, most operating systems support Inter Process Communication (IPC) resources, such as pipes and sockets. IPC is used not just for communication between processes on the same system, but processes on different systems. Most implementations of the Java virtual machine run as a single process. A Java application can create additional processes using a ProcessBuilder object. Multiprocess applications are beyond the scope of this lesson. Threads Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process. Threads exist within a process every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication. Multithreaded execution is an essential feature of the Java platform. Every application has at least one thread or several, if you count "system" threads that do things like memory management and signal handling. But from the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section.

Thread Objects Each thread is associated with an instance of the class Thread. There are two basic strategies for using Thread objects to create a concurrent application.

To directly control thread creation and management, simply instantiate Thread each time the application needs to initiate an asynchronous task. To abstract thread management from the rest of your application, pass the application's tasks to an executor.

This section documents the use of Thread objects. Executors are discussed with other high-level concurrency objects. Defining and Starting a Thread An application that creates an instance of Thread must provide the code that will run in that thread. There are two ways to do this:

Provide a Runnable object. The Runnable interface defines a single method, run, meant to contain the code executed in the thread. The Runnable object is passed to the Thread constructor, as in the HelloRunnable example: public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new Thread(new HelloRunnable())).start(); } } Subclass Thread. The Thread class itself implements Runnable, though its run method does nothing. An application can subclass Thread, providing its own implementation of run, as in the HelloThread example: public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new HelloThread()).start(); } }

Notice that both examples invoke Thread.start in order to start the new thread. Which of these idioms should you use? The first idiom, which employs a Runnable object, is more general, because the Runnable object can subclass a class other than Thread. The second idiom is easier to use in simple applications, but is limited by the fact that your task class must be a descendant of Thread. This lesson focuses on the first approach, which separates the Runnable task from the Thread object that executes the task. Not only is this approach more flexible, but it is applicable to the high-level thread management APIs covered later. The Thread class defines a number of methods useful for thread management. These include static methods, which provide information about, or affect the status of, the thread invoking the method. The other methods are invoked from other threads involved in managing the thread and Thread object. We'll examine some of these methods in the following sections. Pausing Execution with Sleep Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system. The sleep method can also be used for pacing, as shown in the example that follows, and waiting for another thread with duties that are understood to have time requirements, as with the SimpleThreads example in a later section. Two overloaded versions of sleep are provided: one that specifies the sleep time to the millisecond and one that specifies the sleep time to the nanosecond. However, these sleep times are not guaranteed to be precise, because they are limited by the facilities provided by the underlying OS. Also, the sleep period can be terminated by interrupts, as we'll see in a later section. In any case, you cannot assume that invoking sleep will suspend the thread for precisely the time period specified. The SleepMessages example uses sleep to print messages at four-second intervals: public class SleepMessages { public static void main(String args[]) throws InterruptedException { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; for (int i = 0; i < importantInfo.length; i++) { //Pause for 4 seconds Thread.sleep(4000);

//Print a message System.out.println(importantInfo[i]); } } } Notice that main declares that it throws InterruptedException. This is an exception that sleep throws when another thread interrupts the current thread while sleep is active. Since this application has not defined another thread to cause the interrupt, it doesn't bother to catch InterruptedException. Synchronization Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors. The tool needed to prevent these errors is synchronization.

Thread Interference describes how errors are introduced when multiple threads access shared data. Memory Consistency Errors describes errors that result from inconsistent views of shared memory. Synchronized Methods describes a simple idiom that can effectively prevent thread interference and memory consistency errors. Implicit Locks and Synchronization describes a more general synchronization idiom, and describes how synchronization is based on implicit locks. Atomic Access talks about the general idea of operations that can't be interfered with by other threads.

Difference between Multiprocessing and Multithreading Multiprocessing Multithreading 1. More than one process running simultaneously 1. More than one thread running simultaneously. 2. Its part of a program 2. Its part of a program 3. Its a heavy wait process 3. Its a light wait process. Thread States(Life-Cycle of a Thread) The Life cycle of a thread contains several states. At any time the thread is falls into any one of the states. At anytime a thread is said tobe in one or more states. The thread that was just created is in the born state. The thread remains in this state until the threads start methods Is called . This causes the thread to enter the ready state.

The highest priority ready thread enter the running state when the system assigns a processor to the thread i.e., the thread begins executing. When a running thread calls wait the thread enters into a waiting state for the particular object on which wait was called. Every thread in the waiting state for a given object becomes ready on a call to notify all by another thread associated with that object.

Daemon threads A daemon thread is one that is supposed to provide a general service in the background as long as the program is running, but it not part of the essence of the program.

UNIT 6 EVENT HANDLING :

Introduction :
Events : An event is an object that describes a state change in a source. Even driven is a consequence interaction of the user with the GUI.

Event Sources :
A source is an object that generates an event. This occurs when the internal state of that object changes in some way. Sources may generate more than one type of event.

Delegation Event Model :


In java 1.0 the action() method is used to perform any actions that are provided with the controls. But the action() method is now deprecated. The new technique in java1.1 and java 2 is Event DelegationModel.

Event Listeners :
A listener is an object that is notified when an event occurs. It has 2 requirements. 1. It must have been registered with one or more sources to receive notifications about the specific type of events. 2. It must implement methods to receive and process the notifications.

Event Classes :
Event classes are used to handle Java event handling mechanism. At the root of the Java event class hierarchy is EventObject. Which is in the java.util package. It is the superclass for all events. It provides a constructor as EventObject(Object x)

MouseEvent Class :
The MouseEvent Class defines types of mouse events. It defines the following integer constants that can be used to identify them : MOUSE_CLICKED : The user clicked the mouse MOUSE_DRAGGED : The user dragged the mouse MOUSE_ENTERED : The mouse entered a component.

KeyEvent Class :
A KeyEvent is generated when keyboard input occurs. There are 3 types of key events. Which are identified by these integer constants. KEY_PRESSED KEY_RELEASED KEY_TYPED

Key Listener Interface :


The Interface defines three methods 1. void keyPressed(KeyEvent me) : It invokes when a key is pressed

2. void keyReleased(KeyEvent me) : it invokes when a key is released.

Adapter Classes:
An adapter class provides an empty implementation of all methods in an event listener interface. Adapter classes are useful when we want to receive and process only some of the events that are handled by a particular event listener interface.

AWT CONTROLS Introduction:


Controls are components that allow a user to interact with our application in various ways. A layout manager automatically positions components with in a container. The appearance of window is determined by a combination of the controls that it contains and the layout manager used to position them.

The AWT supports the following types of controls :


Labels Push buttons Check boxes Choice lists Lists Scroll bars Text editing

Adding Controls :
First created an instance of the desired controland hten add it to a window by calling add() method, which is defined by Container.

Syntax : component add(component obj) Removing controls


We want to remove a control from a window when the control is no longer needed, call the method remove(). This method is also defined by Container. Syntax : void remove ( component obj)

Labels :
Label is a text information that display on the GUI as a string. These are passive controls that do not support any interaction with the user. Label defines the following constructors: Label() Label(String str) Label(String str, int how)

Buttons :
A push button is a component that contains a label and that generates an event it is pressed. Push buttons are object of type Button.

Handling Buttons :
ActionEvent Class : An ActionEvent is generated when a button is pressed, a list item is double-clicked, or menu item is selected.

Check Boxes:
A Check Box is a control that is used to turn an option on or off. It consists of a small box that can either contain mark or not. There is a label associated with each check box that describes the option that box represents. Checkbox() Checkbox(String str) Checkbox(String str, Boolean on) Checkbox(String str, Boolean on, CheckboxGroup ch)

Check boxGroup :
Collection of check boxes is placed under one group is considered as checkboxGroup. These Checkboxes are often called radio buttons, since one choice is selected at any one time.

Choice Control :
The choice class is used to create a pop-up of items from which the user may choose. A choice control is a form of menu.

Lists :
The List class provides a compact, multiple-choice, scrolling section list, The list object can be constructed to show any number of choices in the visible window. It can also be created to allow multiple selections. List provides these constructors. List() List(int nrows) List(int nrows, Boolean select)

Scroll Bars :

Scroll bars are used to select continuous values between a specified minimum and maximum. Scroll bars may be oriented horizontally or vertically. A scroll bar is actually a composite of several individual parts.

Text Area:
TextField is useful to enter only one line of information. If we want to enter more than one line of data it is not possible with the TextField. To handle these situaltions, the AWT includes a simple multiline editior called TextArea, Constructors of the TextArea are : TextArea() TextArea(int nlines, int nchars) TextArea(String str) TextArea(String str, int nlines, int nchars) TextArea(string str, int nlines, int nchars, int sbars) LAYOUT MANAGER:

Layout Manager
A Layout Mangeris an instance of any class that implements the LayoutManager interface. The layout manager is set by the setLayout() method. If no call to setLayout() is made, then the default layout manager is used. The SetLayout() method has the following general form. Void setLayout(LayoutManger layoutObj)

FlowLayout
The default manager is FlowLayout. FlowLayout implements a simple layout style, which is similar to how words flow in a text editor. Components are laid out from the upper-left corner, left to right and top to bottom.

BorderLayout
The BorderLayout class implements a common layout style for top-level windows. It has four narrow, fixed-width components at the edges and one large area in the center.

CardLayout:
The CardLayout class is stores several different layout. Each layout can be thought of as being on a separate index card in a deck that can be shuffled so that any card is on top at a given time.

UNIT-7 APPLETS

Introduction
Java programs are generally classified into 2 ways as Application programs and Applet programs Application Programs : Application programs are those programs normally created, compiled and executed as similar to the other languages.

Applet Programs : Applet programs are small programs that are primarily used in
Internet programming. These programs are either developed in local systems or in remote systems and are executed by either a java compatible web browser or Appletviewer

Local Applet : When a web page is trying to find a local applet, it does not need to use
the Internet and therefore the local system does not require the Internet connection.

Applet Life Cycle


Every java Applet inherits a set of default behaviors from the Applet class defined in jva.applet package. When an applet is loaded, it undergoes a series of changes in its states.

Exit of Browser :
Note 1. 2. 3. 4. 1 : All the methods are automatically to called when any applet begin execution. The applet execution follows the above order. In every applet it doesnt need to place all the methods. class hierarchy of the applet is java.lang.object

Passing Parameters to Applets It is also possible to supply user-defined parameters to an applet using <PARAM> tags. Each <PARAM> tag has a name attribute and value attribute. Inside the applet code, the applet can refer to theat parameter by name to find its value. To retrieve the parameter, use the getparameter() method. Lesson: A Brief Introduction to the Swing Package This lesson gives you a brief introduction to the capabilities of the Java SE platform that pertain to developing programs with graphical user interfaces (GUIs). Next, it shows you a demo (sample code provided) that showcases many of these features. The next lesson, Swing Features discusses these capabilities in more detail.

What is Swing?

The Swing toolkit, shipped as part of the Java SE platform, provides a rich set of GUI components. But Swing offers much more functionality than a collection of standard widgets. This section takes a look at Swing's rich functionality. A Swing Demo A rich multi-class Swing application, PasswordStore, is presented. The source code is provided as a reference to the user. What is Swing? To create a Java program with a graphical user interface (GUI), you'll want to learn about Swing. The Swing toolkit includes a rich set of components for building GUIs and adding interactivity to Java applications. Swing includes all the components you would expect from a modern toolkit: table controls, list controls, tree controls, buttons, and labels. Swing is far from a simple component toolkit, however. It includes rich undo support, a highly customizable text package, integrated internationalization and accessibility support. To truly leverage the cross-platform capabilities of the Java platform, Swing supports numerous look and feels, including the ability to create your own look and feel. The ability to create a custom look and feel is made easier with Synth, a look and feel specifically designed to be customized. Swing wouldn't be a component toolkit without the basic user interface primitives such as drag and drop, event handling, customizable painting, and window management. Swing is part of the Java Foundation Classes (JFC). The JFC also include other features important to a GUI program, such as the ability to add rich graphics functionality and the ability to create a program that can work in different languages and by users with different input devices. The following list shows some of the features that Swing and the Java Foundation Classes provide. Swing GUI Components The Swing toolkit includes a rich array of components: from basic components, such as buttons and check boxes, to rich and complex components, such as tables and text. Even deceptively simple components, such as text fields, offer sophisticated functionality, such as formatted text input or password field behavior. There are file browsers and dialogs to suit most needs, and if not, customization is possible. If none of Swing's provided components are exactly what you need, you can leverage the basic Swing component functionality to create your own. Java 2D API To make your application stand out; convey information visually; or add figures, images, or animation to your GUI, you'll want to use the Java 2DTM API. Because Swing is built on the 2D package, it's trivial to make use of 2D within Swing components. Adding images, drop shadows, compositing it's easy with Java 2D.

Pluggable Look-and-Feel Support Any program that uses Swing components has a choice of look and feel. The JFC classes shipped by Sun and Apple provide a look and feel that matches that of the platform. The Synth package allows you to create your own look and feel. The GTK+ look and feel makes hundreds of existing look and feels available to Swing programs. A program can specify the look and feel of the platform it is running on, or it can specify to always use the Java look and feel, and without recompiling, it will just work. Or, you can ignore the issue and let the UI manager sort it out. Data Transfer Data transfer, via cut, copy, paste, and drag and drop, is essential to almost any application. Support for data transfer is built into Swing and works between Swing components within an application, between Java applications, and between Java and native applications. Internationalization This feature allows developers to build applications that can interact with users worldwide in their own languages and cultural conventions. Applications can be created that accept input in languages that use thousands of different characters, such as Japanese, Chinese, or Korean. Swing's layout managers make it easy to honor a particular orientation required by the UI. For example, the UI will appear right to left in a locale where the text flows right to left. This support is automatic: You need only code the UI once and then it will work for left to right and right to left, as well as honor the appropriate size of components that change as you localize the text. Accessibility API People with disabilities use special software assistive technologies that mediates the user experience for them. Such software needs to obtain a wealth of information about the running application in order to represent it in alternate media: for a screen reader to read the screen with synthetic speech or render it via a Braille display, for a screen magnifier to track the caret and keyboard focus, for on-screen keyboards to present dynamic keyboards of the menu choices and toolbar items and dialog controls, and for voice control systems to know what the user can control with his or her voice. The accessibility API enables these assistive technologies to get the information they need, and to programmatically manipulate the elements that make up the graphical user interface. Undo Framework API Swing's undo framework allows developers to provide support for undo and redo. Undo support is built in to Swing's text component. For other components, Swing supports an unlimited number of actions to undo and redo, and is easily adapted to an application. For example, you could easily enable undo to add and remove elements from a table. Flexible Deployment Support

If you want your program to run within a browser window, you can create it as an applet and run it using Java Plug-in, which supports a variety of browsers, such as Internet Explorer, Firefox, and Safari. If you want to create a program that can be launched from a browser, you can do this with Java Web Start. Of course, your application can also run outside of browser as a standard desktop application. For more information on deploying an application, see the Deployment trail in this tutorial. This trail provides an overview of Swing capabilities, beginning with a demo that showcases many of these features. When you are ready to begin coding, the Creating a GUI with JFC/Swing trail provides the programming techniques to take advantage of these features. Next, a demo shows many of these features. A Swing Demo Here is an example of an application, PasswordStore, that illustrates some of Swing's rich feature set. PasswordStore allows the user to manage login information for various hosts. It also generates passwords, evaluates the effectiveness of a password, and allows you to store notes about a particular host or assign an icon to represent the host. Text The Java 2D API has various text rendering capabilities including methods for rendering strings and entire classes for setting font attributes and performing text layout. If you just want to draw a static text string, the most direct way to render it directly through the Graphics class by using the drawString method. To specify the font, you use the setFont method of the Graphics class. If you want to implement your own text-editing routines or need more control over the layout of the text than the text components provide, you can use the Java 2D text layout classes in the java.awt.font package. Fonts The shapes that a font uses to represent the characters in a string are called glyphs. A particular character or combination of characters might be represented as one or more glyphs. For example, might be represented by two glyphs, whereas the ligature fi might be represented by a single glyph. A font can be thought of as a collection of glyphs. A single font might have many faces, such as italic and regular. All of the faces in a font have similar typographic features and can be recognized as members of the same family. In other words, a collection of glyphs with a particular style form a font face. A collection of font faces forms a font family. The collection of font families forms the set of fonts that are available on the system.

When you are using the Java 2D API, you specify fonts by using an instance of Font. You can determine what fonts are available by calling the static method GraphicsEnvironment.getLocalGraphicsEnvironment and then querying the returned GraphicsEnvironment. The getAllFonts method returns an array that contains Font instances for all of the fonts available on the system. The getAvailableFontFamilyNames method returns a list of the available font families. Text Layout Before text can be displayed, it must be laid out so that the characters are represented by the appropriate glyphs in the proper positions. The following are two Java 2D mechanisms for managing text layout:

The TextLayout class manages text layout, highlighting, and hit detection. The facilities provided by TextLayout handle the most common cases, including strings with mixed fonts, mixed languages, and bidirectional text. . You can create the own GlyphVector objects by using the Font class and then rendering each GlyphVector object through the Graphics2D class. Thus, you can completely control how text is shaped and positioned. .

Rendering Hints for Text The Java 2D API enables you to control the quality of shapes and text rendering by using rendering hints. Rendering hints are encapsulated by the java.awt.RenderingHints class. As applied to text, this capability is used for antialiasing (which is also known as an smooth edges). For example, the KEY_TEXT_ANTIALIASING hint enables you to control the antialiasing of text separately from the antialiasing of other shapes. To learn more about rendering hints see the Controlling Rendering Quality lesson. Images In the Java 2D API an image is typically a rectangular two-dimensional array of pixels, where each pixel represents the color at that position of the image and where the dimensions represent the horizontal extent (width) and vertical extent (height) of the image as it is displayed. The most important image class for representing such images is the java.awt.image.BufferedImage class. The Java 2D API stores the contents of such images in memory so that they can be directly accessed. Applications can directly create a BufferedImage object or obtain an image from an external image format such as PNG or GIF. In either case, the application can then draw on to image by using Java 2D API graphics calls. So, images are not limited to displaying photographic type images. Different

objects such as line art, text, and other graphics and even other images can be drawn onto an image (as shown on the following images).

The Java 2D API enables you to apply image filtering operations to BufferedImage and includes several built-in filters. For example, the ConvolveOp filter can be used to blur or sharpen images.

UNIT 8
Networking Basics Computers running on the Internet communicate to each other using either the Transmission Control Protocol (TCP) or the User Datagram Protocol (UDP), as this diagram illustrates:

When you write Java programs that communicate over the network, you are programming at the application layer. Typically, you don't need to concern yourself with the TCP and UDP layers. Instead, you can use the classes in the java.net package. These classes provide system-independent network communication. However, to decide which Java classes your programs should use, you do need to understand how TCP and UDP differ.

TCP When two applications want to communicate to each other reliably, they establish a connection and send data back and forth over that connection. This is analogous to making a telephone call. If you want to speak to Aunt Beatrice in Kentucky, a connection is established when you dial her phone number and she answers. You send data back and forth over the connection by speaking to one another over the phone lines. Like the phone company, TCP guarantees that data sent from one end of the connection actually gets to the other end and in the same order it was sent. Otherwise, an error is reported. TCP provides a point-to-point channel for applications that require reliable communications. The Hypertext Transfer Protocol (HTTP), File Transfer Protocol (FTP), and Telnet are all examples of applications that require a reliable communication channel. The order in which the data is sent and received over the network is critical to the success of these applications. When HTTP is used to read from a URL, the data must be received in the order in which it was sent. Otherwise, you end up with a jumbled HTML file, a corrupt zip file, or some other invalid information. Definition: TCP (Transmission Control Protocol) is a connection-based protocol that provides a reliable flow of data between two computers.

UDP The UDP protocol provides for communication that is not guaranteed between two applications on the network. UDP is not connection-based like TCP. Rather, it sends independent packets of data, called datagrams, from one application to another. Sending datagrams is much like sending a letter through the postal service: The order of delivery is not important and is not guaranteed, and each message is independent of any other. Definition: UDP (User Datagram Protocol) is a protocol that sends independent packets of data, called datagrams, from one computer to another with no guarantees about arrival. UDP is not connection-based like TCP. For many applications, the guarantee of reliability is critical to the success of the transfer of information from one end of the connection to the other. However, other forms of communication don't require such strict standards. In fact, they may be slowed down by the extra overhead or the reliable connection may invalidate the service altogether. Consider, for example, a clock server that sends the current time to its client when requested to do so. If the client misses a packet, it doesn't really make sense to resend it because the time will be incorrect when the client receives it on the second try. If the client makes two requests and receives packets from the server out of order, it doesn't really matter because the client can figure out that the packets are out of order and make another request. The reliability of TCP is unnecessary in this instance because it causes performance degradation and may hinder the usefulness of the service. Another example of a service that doesn't need the guarantee of a reliable channel is the ping command. The purpose of the ping command is to test the communication between two programs over the network. In fact, ping needs to know about dropped or out-oforder packets to determine how good or bad the connection is. A reliable channel would invalidate this service altogether. The UDP protocol provides for communication that is not guaranteed between two applications on the network. UDP is not connection-based like TCP. Rather, it sends independent packets of data from one application to another. Sending datagrams is much like sending a letter through the mail service: The order of delivery is not important and is not guaranteed, and each message is independent of any others. Note: Many firewalls and routers have been configured not to allow UDP packets. If you're having trouble connecting to a service outside your firewall, or if clients are having trouble connecting to your service, ask your system administrator if UDP is permitted. Understanding Ports Generally speaking, a computer has a single physical connection to the network. All data destined for a particular computer arrives through that connection. However, the data

may be intended for different applications running on the computer. So how does the computer know to which application to forward the data? Through the use of ports. Data transmitted over the Internet is accompanied by addressing information that identifies the computer and the port for which it is destined. The computer is identified by its 32-bit IP address, which IP uses to deliver data to the right computer on the network. Ports are identified by a 16-bit number, which TCP and UDP use to deliver the data to the right application. In connection-based communication such as TCP, a server application binds a socket to a specific port number. This has the effect of registering the server with the system to receive all data destined for that port. A client can then rendezvous with the server at the server's port, as illustrated here:

Definition: The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer. In datagram-based communication such as UDP, the datagram packet contains the port number of its destination and UDP routes the packet to the appropriate application, as illustrated in this figure:

Port numbers range from 0 to 65,535 because ports are represented by 16-bit numbers. The port numbers ranging from 0 - 1023 are restricted; they are reserved for use by wellknown services such as HTTP and FTP and other system services. These ports are called well-known ports. Your applications should not attempt to bind to them. Networking Classes in the JDK 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. Lesson: Working with URLs

URL is the acronym for Uniform Resource Locator. It is a reference (an address) to a resource on the Internet. You provide URLs to your favorite Web browser so that it can locate files on the Internet in the same way that you provide addresses on letters so that the post office can locate your correspondents. Java programs that interact with the Internet also may use URLs to find the resources on the Internet they wish to access. Java programs can use a class called URL in the java.net package to represent a URL address. Terminology Note: The term URL can be ambiguous. It can refer to an Internet address or a URL object in a Java program. Where the meaning of URL needs to be specific, this text uses "URL address" to mean an Internet address and "URL object" to refer to an instance of the URL class in a program. What Is a URL? A URL takes the form of a string that describes how to find a resource on the Internet. URLs have two main components: the protocol needed to access the resource and the location of the resource. Creating a URL Within your Java programs, you can create a URL object that represents a URL address. The URL object always refers to an absolute URL but can be constructed from an absolute URL, a relative URL, or from URL components. Parsing a URL Gone are the days of parsing a URL to find out the host name, filename, and other information. With a valid URL object you can call any of its accessor methods to get all of that information from the URL without doing any string parsing! Reading Directly from a URL This section shows how your Java programs can read from a URL using the openStream() method. Connecting to a URL If you want to do more than just read from a URL, you can connect to it by calling openConnection() on the URL. The openConnection() method returns a URLConnection object that you can use for more general communications with the URL, such as reading from it, writing to it, or querying it for content and other information. Reading from and Writing to a URLConnection

Some URLs, such as many that are connected to cgi-bin scripts, allow you to (or even require you to) write information to the URL. For example, a search script may require detailed query data to be written to the URL before the search can be performed. This section shows you how to write to a URL and how to get results back. What Is a URL? If you've been surfing the Web, you have undoubtedly heard the term URL and have used URLs to access HTML pages from the Web. It's often easiest, although not entirely accurate, to think of a URL as the name of a file on the World Wide Web because most URLs refer to a file on some machine on the network. However, remember that URLs also can point to other resources on the network, such as database queries and command output. Definition: URL is an acronym for Uniform Resource Locator and is a reference (an address) to a resource on the Internet. The following is an example of a URL which addresses the Java Web site hosted by Sun Microsystems:

As in the previous diagram, a URL has two main components:


Protocol identifier Resource name

Note that the protocol identifier and the resource name are separated by a colon and two forward slashes. The protocol identifier indicates the name of the protocol to be used to fetch the resource. The example uses the Hypertext Transfer Protocol (HTTP), which is typically used to serve up hypertext documents. HTTP is just one of many different protocols used to access different types of resources on the net. Other protocols include File Transfer Protocol (FTP), Gopher, File, and News. The resource name is the complete address to the resource. The format of the resource name depends entirely on the protocol used, but for many protocols, including HTTP, the resource name contains one or more of the components listed in the following table: Host Name Filename Port Number Reference The name of the machine on which the resource lives. The pathname to the file on the machine. The port number to which to connect (typically optional). A reference to a named anchor within a resource that usually identifies a

specific location within a file (typically optional). For many protocols, the host name and the filename are required, while the port number and reference are optional. For example, the resource name for an HTTP URL must specify a server on the network (Host Name) and the path to the document on that machine (Filename); it also can specify a port number and a reference. In the URL for the Java Web site java.sun.com is the host name and an empty path or the trailing slash is shorthand for the file named /index.html. Creating a URL The easiest way to create a URL object is from a String that represents the humanreadable form of the URL address. This is typically the form that another person will use for a URL. For example, the URL for the Gamelan site, which is a directory of Java resources, takes the following form: http://www.gamelan.com/ In your Java program, you can use a String containing this text to create a URL object: URL gamelan = new URL("http://www.gamelan.com/"); The URL object created above represents an absolute URL. An absolute URL contains all of the information necessary to reach the resource in question. You can also create URL objects from a relative URL address. Creating a URL Relative to Another A relative URL contains only enough information to reach the resource relative to (or in the context of) another URL. Relative URL specifications are often used within HTML files. For example, suppose you write an HTML file called JoesHomePage.html. Within this page, are links to other pages, PicturesOfMe.html and MyKids.html, that are on the same machine and in the same directory as JoesHomePage.html. The links to PicturesOfMe.html and MyKids.html from JoesHomePage.html could be specified just as filenames, like this: <a href="PicturesOfMe.html">Pictures of Me</a> <a href="MyKids.html">Pictures of My Kids</a> These URL addresses are relative URLs. That is, the URLs are specified relative to the file in which they are contained--JoesHomePage.html. In your Java programs, you can create a URL object from a relative URL specification. For example, suppose you know two URLs at the Gamelan site: http://www.gamelan.com/pages/Gamelan.game.html http://www.gamelan.com/pages/Gamelan.net.html You can create URL objects for these pages relative to their common base URL: http://www.gamelan.com/pages/ like this: URL gamelan = new URL("http://www.gamelan.com/pages/");

URL gamelanGames = new URL(gamelan, "Gamelan.game.html"); URL gamelanNetwork = new URL(gamelan, "Gamelan.net.html"); This code snippet uses the URL constructor that lets you create a URL object from another URL object (the base) and a relative URL specification. The general form of this constructor is: URL(URL baseURL, String relativeURL) The first argument is a URL object that specifies the base of the new URL. The second argument is a String that specifies the rest of the resource name relative to the base. If baseURL is null, then this constructor treats relativeURL like an absolute URL specification. Conversely, if relativeURL is an absolute URL specification, then the constructor ignores baseURL. This constructor is also useful for creating URL objects for named anchors (also called references) within a file. For example, suppose the Gamelan.network.html file has a named anchor called BOTTOM at the bottom of the file. You can use the relative URL constructor to create a URL object for it like this: URL gamelanNetworkBottom = new URL(gamelanNetwork, "#BOTTOM"); Other URL Constructors The URL class provides two additional constructors for creating a URL object. These constructors are useful when you are working with URLs, such as HTTP URLs, that have host name, filename, port number, and reference components in the resource name portion of the URL. These two constructors are useful when you do not have a String containing the complete URL specification, but you do know various components of the URL. For example, suppose you design a network browsing panel similar to a file browsing panel that allows users to choose the protocol, host name, port number, and filename. You can construct a URL from the panel's components. The first constructor creates a URL object from a protocol, host name, and filename. The following code snippet creates a URL to the Gamelan.net.html file at the Gamelan site: new URL("http", "www.gamelan.com", "/pages/Gamelan.net.html"); This is equivalent to new URL("http://www.gamelan.com/pages/Gamelan.net.html"); The first argument is the protocol, the second is the host name, and the last is the pathname of the file. Note that the filename contains a forward slash at the beginning. This indicates that the filename is specified from the root of the host. The final URL constructor adds the port number to the list of arguments used in the previous constructor: URL gamelan = new URL("http", "www.gamelan.com", 80, "pages/Gamelan.network.html");

This creates a URL object for the following URL: http://www.gamelan.com:80/pages/Gamelan.network.html If you construct a URL object using one of these constructors, you can get a String containing the complete URL address by using the URL object's toString method or the equivalent toExternalForm method. URL addresses with Special characters Some URL addresses contain special characters, for example the space character. Like this: http://foo.com/hello world/ To make theses characters legal they need to encoded before passing them to the URL constructor. URL url = new URL("http://foo.com/hello%20world"); Encoding the special character(s) in this example is easy as there is only one character that needs encoding, but for URL addresses that have several of these characters or if you are unsure when writing your code what URL addresses you will need to access, you can use the multi-argument constructors of the java.net.URI class to automatically take care of the encoding for you. URI uri = new URI("http", "foo.com", "/hello world/", ""); And then convert the URI to a URL. URL url = uri.toURL(); MalformedURLException Each of the four URL constructors throws a MalformedURLException if the arguments to the constructor refer to a null or unknown protocol. Typically, you want to catch and handle this exception by embedding your URL constructor statements in a try/catch pair, like this: try { URL myURL = new URL(. . .) } catch (MalformedURLException e) { ... // exception handler code here ... } See Exceptions for information about handling exceptions. Note: URLs are "write-once" objects. Once you've created a URL object, you cannot change any of its attributes (protocol, host name, filename, or port number). Parsing a URL The URL class provides several methods that let you query URL objects. You can get the protocol, authority, host name, port number, path, query, filename, and reference from a URL using these accessor methods: getProtocol Returns the protocol identifier component of the URL. getAuthority

Returns the authority component of the URL. getHost Returns the host name component of the URL. getPort Returns the port number component of the URL. The getPort method returns an integer that is the port number. If the port is not set, getPort returns -1. getPath Returns the path component of this URL. getQuery Returns the query component of this URL. getFile Returns the filename component of the URL. The getFile method returns the same as getPath, plus the concatenation of the value of getQuery, if any. getRef Returns the reference component of the URL. Note: Remember that not all URL addresses contain these components. The URL class provides these methods because HTTP URLs do contain these components and are perhaps the most commonly used URLs. The URL class is somewhat HTTP-centric. You can use these getXXX methods to get information about the URL regardless of the constructor that you used to create the URL object. The URL class, along with these accessor methods, frees you from ever having to parse URLs again! Given any string specification of a URL, just create a new URL object and call any of the accessor methods for the information you need. This small example program creates a URL from a string specification and then uses the URL object's accessor methods to parse the URL: import java.net.*; import java.io.*; public class ParseURL { public static void main(String[] args) throws Exception { URL aURL = new URL("http://java.sun.com:80/docs/books/tutorial" + "/index.html?name=networking#DOWNLOADING"); System.out.println("protocol = " + aURL.getProtocol()); System.out.println("authority = " + aURL.getAuthority()); System.out.println("host = " + aURL.getHost()); System.out.println("port = " + aURL.getPort()); System.out.println("path = " + aURL.getPath()); System.out.println("query = " + aURL.getQuery()); System.out.println("filename = " + aURL.getFile()); System.out.println("ref = " + aURL.getRef()); } }

Here's the output displayed by the program: protocol = http authority = java.sun.com:80 host = java.sun.com port = 80 path = /docs/books/tutorial/index.html query = name=networking filename = /docs/books/tutorial/index.html?name=networking ref = DOWNLOADING Reading Directly from a URL After you've successfully created a URL, you can call the URL's openStream() method to get a stream from which you can read the contents of the URL. The openStream() method returns a java.io.InputStreamobject, so reading from a URL is as easy as reading from an input stream. The following small Java program uses openStream() to get an input stream on the URL http://www.yahoo.com/. It then opens a BufferedReader on the input stream and reads from the BufferedReader thereby reading from the URL. Everything read is copied to the standard output stream: import java.net.*; import java.io.*; public class URLReader { public static void main(String[] args) throws Exception { URL yahoo = new URL("http://www.yahoo.com/"); BufferedReader in = new BufferedReader( new InputStreamReader( yahoo.openStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } } When you run the program, you should see, scrolling by in your command window, the HTML commands and textual content from the HTML file located at http://www.yahoo.com/. Alternatively, the program might hang or you might see an exception stack trace. If either of the latter two events occurs, you may have to set the proxy host so that the program can find the Yahoo server. Connecting to a URL

After you've successfully created a URL object, you can call the URL object's openConnection method to get a URLConnection object, or one of its protocol specific subclasses, e.g. java.net.HttpURLConnection You can use this URLConnection object to setup parameters and general request properties that you may need before connecting. Connection to the remote object represented by the URL is only initiated when the URLConnection.connect method is called. When you do this you are initializing a communication link between your Java program and the URL over the network. For example, you can open a connection to the Yahoo site with the following code: try { URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yahooConnection = yahoo.openConnection(); yahooConnection.connect(); } catch (MalformedURLException e) { // new URL() failed ... } catch (IOException e) { // openConnection() failed ... } A new URLConnection object is created every time by calling the openConnection method of the protocol handler for this URL. You are not always required to explicitly call the connect method to initiate the connection. Operations that depend on being connected, like getInputStream, getOutputStream, etc, will implicitly perform the connection, if necessary. Now that you've successfully connected to your URL, you can use the URLConnection object to perform actions such as reading from or writing to the connection. The next section shows you how. Reading from and Writing to a URLConnection The URLConnection class contains many methods that let you communicate with the URL over the network. URLConnection is an HTTP-centric class; that is, many of its methods are useful only when you are working with HTTP URLs. However, most URL protocols allow you to read from and write to the connection. This section describes both functions. Reading from a URLConnection The following program performs the same function as the URLReader program shown in Reading Directly from a URL. However, rather than getting an input stream directly from the URL, this program explicitly retrieves a URLConnection object and gets an input stream from the

connection. The connection is opened implicitly by calling getInputStream. Then, like URLReader, this program creates a BufferedReader on the input stream and reads from it. The bold statements highlight the differences between this example and the previous import java.net.*; import java.io.*; public class URLConnectionReader { public static void main(String[] args) throws Exception { URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yc = yahoo.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( yc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } } The output from this program is identical to the output from the program that opens a stream directly from the URL. You can use either way to read from a URL. However, reading from a URLConnection instead of reading directly from a URL might be more useful. This is because you can use the URLConnection object for other tasks (like writing to the URL) at the same time. Again, if the program hangs or you see an error message, you may have to set the proxy host so that the program can find the Yahoo server. Writing to a URLConnection Many HTML pages contain forms-- text fields and other GUI objects that let you enter data to send to the server. After you type in the required information and initiate the query by clicking a button, your Web browser writes the data to the URL over the network. At the other end the server receives the data, processes it, and then sends you a response, usually in the form of a new HTML page. Many of these HTML forms use the HTTP POST METHOD to send data to the server. Thus writing to a URL is often called posting to a URL. The server recognizes the POST request and reads the data sent from the client. For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps: 1. Create a URL.

2. 3. 4. 5. 6. 7.

Retrieve the URLConnection object. Set output capability on the URLConnection. Open a connection to the resource. Get an output stream from the connection. Write to the output stream. Close the output stream.

Here is a small servlet named ReverseServlet ( or if you prefer a cgi-bin script ). You can use this servlet to test the following example program. The servlet running in a container reads from its InputStream, reverses the string, and writes it to its OutputStream. The servlet requires input of the form string=string_to_reverse, where string_to_reverse is the string whose characters you want displayed in reverse order. Here's an example program that runs the ReverseServlet over the network through a URLConnection: import java.io.*; import java.net.*; public class Reverse { public static void main(String[] args) throws Exception { if (args.length != 2) { System.err.println("Usage: java Reverse " + "http://<location of your servlet/script>" + " string_to_reverse"); System.exit(1); } String stringToReverse = URLEncoder.encode(args[1], "UTF-8"); URL url = new URL(args[0]); URLConnection connection = url.openConnection(); connection.setDoOutput(true); OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream()); out.write("string=" + stringToReverse); out.close(); BufferedReader in = new BufferedReader( new InputStreamReader( connection.getInputStream()));

String decodedString; while ((decodedString = in.readLine()) != null) { System.out.println(decodedString); } in.close(); } } Let's examine the program and see how it works. First, the program processes its command-line arguments: if (args.length != 2) { System.err.println("Usage: java Reverse " + "http://<location of your servlet/script>" + " string_to_reverse"); System.exit(1); } String stringToReverse = URLEncoder.encode(args[1], "UTF-8"); These statements ensure that the user provides two and only two command-line arguments to the program. The command-line arguments are the location of the ReverseServlet and the string that will be reversed. It may contain spaces or other nonalphanumeric characters. These characters must be encoded because the string is processed on its way to the server. The URLEncoder class methods encode the characters. Next, the program creates the URL object, and sets the connection so that it can write to it: URL url = new URL(args[0]); URLConnection connection = url.openConnection(); connection.setDoOutput(true); The program then creates an output stream on the connection and opens an OutputStreamWriter on it: OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); If the URL does not support output, getOutputStream method throws an UnknownServiceException. If the URL does support output, then this method returns an output stream that is connected to the input stream of the URL on the server side--the client's output is the server's input. Next, the program writes the required information to the output stream and closes the stream: out.write("string=" + stringToReverse); out.close();

This code writes to the output stream using the write method. So you can see that writing data to a URL is as easy as writing data to a stream. The data written to the output stream on the client side is the input for the servlet on the server side. The Reverse program constructs the input in the form required by the script by prepending string= to the encoded string to be reversed. The serlvet reads the information you write, performs a reverse operation on the string value, and then sends this back to you. You now need to read the string the server has sent back. The Reverse program does it like this: BufferReaderder in = new BufferedReader( new InputStreamReader( connection.getInputStream())); String decodedString; while ((decodedString = in.readLine()) != null) { System.out.println(decodedString); } in.close(); If your ReverseServlet is located at http://foobar.com/servlet/ReverseServlet, then when you run the Reverse program using http://foobar.com/servlet/ReverseServlet "Reverse Me" as the argument (including the double quote marks), you should see this output: Reverse Me reversed is: eM esreveR Lesson: All About Sockets URLs and URLConnections provide a relatively high-level mechanism for accessing resources on the Internet. Sometimes your programs require lower-level network communication, for example, when you want to write a client-server application. In client-server applications, the server provides some service, such as processing database queries or sending out current stock prices. The client uses the service provided by the server, either displaying database query results to the user or making stock purchase recommendations to an investor. The communication that occurs between the client and the server must be reliable. That is, no data can be dropped and it must arrive on the client side in the same order in which the server sent it. TCP provides a reliable, point-to-point communication channel that client-server applications on the Internet use to communicate with each other. To communicate over TCP, a client program and a server program establish a connection to one another. Each program binds a socket to its end of the connection. To communicate, the client and the server each reads from and writes to the socket bound to the connection. What Is a Socket?

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.

Reading from and Writing to a Socket This page contains a small example that illustrates how a client program can read from and write to a socket. Writing a Client/Server Pair The previous page showed an example of how to write a client program that interacts with an existing server via a Socket object. This page shows you how to write a program that implements the other side of the connection--a server program. What Is a Socket? Normally, a server runs on a specific computer and has a socket that is bound to a specific port number. The server just waits, listening to the socket for a client to make a connection request. On the client-side: The client knows the hostname of the machine on which the server is running and the port number on which the server is listening. To make a connection request, the client tries to rendezvous with the server on the server's machine and port. The client also needs to identify itself to the server so it binds to a local port number that it will use during this connection. This is usually assigned by the system.

If everything goes well, the server accepts the connection. Upon acceptance, the server gets a new socket bound to the same local port and also has its remote endpoint set to the address and port of the client. It needs a new socket so that it can continue to listen to the original socket for connection requests while tending to the needs of the connected client.

On the client side, if the connection is accepted, a socket is successfully created and the client can use the socket to communicate with the server.

The client and server can now communicate by writing to or reading from their sockets. Definition: A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent. An endpoint is a combination of an IP address and a port number. Every TCP connection can be uniquely identified by its two endpoints. That way you can have multiple connections between your host and the server. The java.net package in the Java platform provides a class, Socket, that implements one side of a two-way connection between your Java program and another program on the network. The Socket class sits on top of a platform-dependent implementation, hiding the details of any particular system from your Java program. By using the java.net.Socket class instead of relying on native code, your Java programs can communicate over the network in a platform-independent fashion. Additionally, java.net includes the ServerSocket class, which implements a socket that servers can use to listen for and accept connections to clients. This lesson shows you how to use the Socket and ServerSocket classes. If you are trying to connect to the Web, the URL class and related classes (URLConnection, URLEncoder) are probably more appropriate than the socket classes. In fact, URLs are a relatively high-level connection to the Web and use sockets as part of the underlying implementation. See Working with URLs for information about connecting to the Web via URLs. Reading from and Writing to a Socket Let's look at a simple example that illustrates how a program can establish a connection to a server program using the Socket class and then, how the client can send data to and receive data from the server through the socket. The example program implements a client, EchoClient, that connects to the Echo server. The Echo server simply receives data from its client and echoes it back. The Echo server is a well-known service that clients can rendezvous with on port 7. EchoClient creates a socket thereby getting a connection to the Echo server. It reads input from the user on the standard input stream, and then forwards that text to the Echo server by writing the text to the socket. The server echoes the input back through the socket to the client. The client program reads and displays the data passed back to it from the server: import java.io.*; import java.net.*;

public class EchoClient { public static void main(String[] args) throws IOException { Socket echoSocket = null; PrintWriter out = null; BufferedReader in = null; try { echoSocket = new Socket("taranis", 7); out = new PrintWriter(echoSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( echoSocket.getInputStream())); } catch (UnknownHostException e) { System.err.println("Don't know about host: taranis."); System.exit(1); } catch (IOException e) { System.err.println("Couldn't get I/O for " + "the connection to: taranis."); System.exit(1); } BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in)); String userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); } out.close(); in.close(); stdIn.close(); echoSocket.close(); } } Note that EchoClient both writes to and reads from its socket, thereby sending data to and receiving data from the Echo server. Let's walk through the program and investigate the interesting parts. The three statements in the try block of the main method are critical. These lines establish the socket connection between the client and the server and open a PrintWriter and a BufferedReader on the socket: echoSocket = new Socket("taranis", 7); out = new PrintWriter(echoSocket.getOutputStream(), true);

in = new BufferedReader(new InputStreamReader( echoSocket.getInputStream())); The first statement in this sequence creates a new Socket object and names it echoSocket. The Socket constructor used here requires the name of the machine and the port number to which you want to connect. The example program uses the host name taranis. This is the name of a hypothetical machine on our local network. When you type in and run this program on your machine, change the host name to the name of a machine on your network. Make sure that the name you use is the fully qualified IP name of the machine to which you want to connect. The second argument is the port number. Port number 7 is the port on which the Echo server listens. The second statement gets the socket's output stream and opens a PrintWriter on it. Similarly, the third statement gets the socket's input stream and opens a BufferedReader on it. The example uses readers and writers so that it can write Unicode characters over the socket. To send data through the socket to the server, EchoClient simply needs to write to the PrintWriter. To get the server's response, EchoClient reads from the BufferedReader. The rest of the program achieves this. If you are not yet familiar with the Java platform's I/O classes, you may wish to read Basic I/O. The next interesting part of the program is the while loop. The loop reads a line at a time from the standard input stream and immediately sends it to the server by writing it to the PrintWriter connected to the socket: String userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); } The last statement in the while loop reads a line of information from the BufferedReader connected to the socket. The readLine method waits until the server echoes the information back to EchoClient. When readline returns, EchoClient prints the information to the standard output. The while loop continues until the user types an end-of-input character. That is, EchoClient reads input from the user, sends it to the Echo server, gets a response from the server, and displays it, until it reaches the end-of-input. The while loop then terminates and the program continues, executing the next four lines of code: out.close(); in.close(); stdIn.close(); echoSocket.close();

These lines of code fall into the category of housekeeping. A well-behaved program always cleans up after itself, and this program is well-behaved. These statements close the readers and writers connected to the socket and to the standard input stream, and close the socket connection to the server. The order here is important. You should close any streams connected to a socket before you close the socket itself. 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. When your client programs are talking to a more complicated server such as an HTTP server, your client program will also be more complicated. However, the basics are much the same as they are in this program: 1. 2. 3. 4. 5. Open a socket. Open an input stream and output stream to the socket. Read from and write to the stream according to the server's protocol. Close the streams. Close the socket.

Only step 3 differs from client to client, depending on the server. The other steps remain largely the same. Writing the Server Side of a Socket This section shows you how to write a server and the client that goes with it. The server in the client/server pair serves up Knock Knock jokes. Knock Knock jokes are favored by children and are usually vehicles for bad puns. They go like this: Server: "Knock knock!" Client: "Who's there?" Server: "Dexter." Client: "Dexter who?" Server: "Dexter halls with boughs of holly." Client: "Groan." The example consists of two independently running Java programs: the client program and the server program. The client program is implemented by a single class, KnockKnockClient, and is very similar to the EchoClient example from the previous section. The server program is implemented by two classes: KnockKnockServer and KnockKnockProtocol, KnockKnockServer contains the main method for the server program and performs the work of listening to the port, establishing connections, and reading from and writing to the socket. KnockKnockProtocol serves up the jokes. It keeps track of the current joke, the current state (sent knock knock, sent clue, and so on), and returns the various text pieces of the joke depending on the current state. This object implements the protocol-the language that the client and server have agreed to use to communicate. The following section looks in detail at each class in both the client and the server and then shows you how to run them.

The Knock Knock Server This section walks through the code that implements the Knock Knock server program. Here is the complete source for the KnockKnockServer class. The server program begins by creating a new ServerSocket object to listen on a specific port (see the statement in bold in the following code segment). When writing a server, choose a port that is not already dedicated to some other service. KnockKnockServer listens on port 4444 because 4 happens to be my favorite number and port 4444 is not being used for anything else in my environment: try { serverSocket = new ServerSocket(4444); } catch (IOException e) { System.out.println("Could not listen on port: 4444"); System.exit(-1); } ServerSocket is a java.net class that provides a system-independent implementation of the server side of a client/server socket connection. The constructor for ServerSocket throws an exception if it can't listen on the specified port (for example, the port is already being used). In this case, the KnockKnockServer has no choice but to exit. If the server successfully binds to its port, then the ServerSocket object is successfully created and the server continues to the next step--accepting a connection from a client (shown in bold): Socket clientSocket = null; try { clientSocket = serverSocket.accept(); } catch (IOException e) { System.out.println("Accept failed: 4444"); System.exit(-1); } The accept method waits until a client starts up and requests a connection on the host and port of this server (in this example, the server is running on the hypothetical machine taranis on port 4444). When a connection is requested and successfully established, the accept method returns a new Socket object which is bound to the same local port and has it's remote address and remote port set to that of the client. The server can communicate with the client over this new Socket and continue to listen for client connection requests on the original ServerSocket This particular version of the program doesn't listen for more client connection requests. However, a modified version of the program is provided in Supporting Multiple Clients. After the server successfully establishes a connection with a client, it communicates with the client using this code:

PrintWriter out = new PrintWriter( clientSocket.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader( clientSocket.getInputStream())); String inputLine, outputLine; // initiate conversation with client KnockKnockProtocol kkp = new KnockKnockProtocol(); outputLine = kkp.processInput(null); out.println(outputLine); while ((inputLine = in.readLine()) != null) { outputLine = kkp.processInput(inputLine); out.println(outputLine); if outputLine.equals("Bye.")) break; } This code: 1. Gets the socket's input and output stream and opens readers and writers on them. 2. Initiates communication with the client by writing to the socket (shown in bold). 3. Communicates with the client by reading from and writing to the socket (the while loop). Step 1 is already familiar. Step 2 is shown in bold and is worth a few comments. The bold statements in the code segment above initiate the conversation with the client. The code creates a KnockKnockProtocol object-the object that keeps track of the current joke, the current state within the joke, and so on. After the KnockKnockProtocol is created, the code calls KnockKnockProtocol's processInput method to get the first message that the server sends to the client. For this example, the first thing that the server says is "Knock! Knock!" Next, the server writes the information to the PrintWriter connected to the client socket, thereby sending the message to the client. Step 3 is encoded in the while loop. As long as the client and server still have something to say to each other, the server reads from and writes to the socket, sending messages back and forth between the client and the server. The server initiated the conversation with a "Knock! Knock!" so afterwards the server must wait for the client to say "Who's there?" As a result, the while loop iterates on a read from the input stream. The readLine method waits until the client responds by writing something to its output stream (the server's input stream). When the client responds, the server passes the client's response to the KnockKnockProtocol object and asks the KnockKnockProtocol object for a suitable reply. The server immediately sends the reply

to the client via the output stream connected to the socket, using a call to println. If the server's response generated from the KnockKnockServer object is "Bye." this indicates that the client doesn't want any more jokes and the loop quits. The KnockKnockServer class is a well-behaved server, so the last several lines of this section of KnockKnockServer clean up by closing all of the input and output streams, the client socket, and the server socket: out.close(); in.close(); clientSocket.close(); serverSocket.close(); The Knock Knock Protocol The KnockKnockProtocol class implements the protocol that the client and server use to communicate. This class keeps track of where the client and the server are in their conversation and serves up the server's response to the client's statements. The KnockKnockServer object contains the text of all the jokes and makes sure that the client gives the proper response to the server's statements. It wouldn't do to have the client say "Dexter who?" when the server says "Knock! Knock!" All client/server pairs must have some protocol by which they speak to each other; otherwise, the data that passes back and forth would be meaningless. The protocol that your own clients and servers use depends entirely on the communication required by them to accomplish the task. The Knock Knock Client The KnockKnockClient class implements the client program that speaks to the KnockKnockServer. KnockKnockClient is based on the EchoClient program in the previous section, Reading from and Writing to a Socket and should be somewhat familiar to you. But we'll go over the program anyway and look at what's happening in the client in the context of what's going on in the server. When you start the client program, the server should already be running and listening to the port, waiting for a client to request a connection. So, the first thing the client program does is to open a socket that is connected to the server running on the hostname and port specified: kkSocket = new Socket("taranis", 4444); out = new PrintWriter(kkSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( kkSocket.getInputStream())); When creating its socket, KnockKnockClient uses the host name taranis, the name of a hypothetical machine on our network. When you type in and run this program, change the

host name to the name of a machine on your network. This is the machine on which you will run the KnockKnockServer. The KnockKnockClient program also specifies the port number 4444 when creating its socket. This is a remote port number--the number of a port on the server machine--and is the port to which KnockKnockServer is listening. The client's socket is bound to any available local port--a port on the client machine. Remember that the server gets a new socket as well. That socket is bound to local port number 4444 on its machine. The server's socket and the client's socket are connected. Next comes the while loop that implements the communication between the client and the server. The server speaks first, so the client must listen first. The client does this by reading from the input stream attached to the socket. If the server does speak, it says "Bye." and the client exits the loop. Otherwise, the client displays the text to the standard output and then reads the response from the user, who types into the standard input. After the user types a carriage return, the client sends the text to the server through the output stream attached to the socket. while ((fromServer = in.readLine()) != null) { System.out.println("Server: " + fromServer); if (fromServer.equals("Bye.")) break; fromUser = stdIn.readLine(); if (fromUser != null) { System.out.println("Client: " + fromUser); out.println(fromUser); } } The communication ends when the server asks if the client wishes to hear another joke, the client says no, and the server says "Bye." In the interest of good housekeeping, the client closes its input and output streams and the socket: out.close(); in.close(); stdIn.close(); kkSocket.close(); Running the Programs You must start the server program first. To do this, run the server program using the Java interpreter, just as you would any other Java application. Remember to run the server on the machine that the client program specifies when it creates the socket.

Next, run the client program. Note that you can run the client on any machine on your network; it does not have to run on the same machine as the server. If you are too quick, you might start the client before the server has a chance to initialize itself and begin listening on the port. If this happens, you will see a stack trace from the client. If this happens, just restart the client. If you forget to change the host name in the source code for the KnockKnockClient program, you will see the following error message: Don't know about host: taranis To fix this, modify the KnockKnockClient program and provide a valid host name for your network. Recompile the client program and try again. If you try to start a second client while the first client is connected to the server, the second client just hangs. The next section, Supporting Multiple Clients, talks about supporting multiple clients. When you successfully get a connection between the client and server, you will see the following text displayed on your screen: Server: Knock! Knock! Now, you must respond with: Who's there? The client echoes what you type and sends the text to the server. The server responds with the first line of one of the many Knock Knock jokes in its repertoire. Now your screen should contain this (the text you typed is in bold): Server: Knock! Knock! Who's there? Client: Who's there? Server: Turnip Now, you respond with: Turnip who?" Again, the client echoes what you type and sends the text to the server. The server responds with the punch line. Now your screen should contain this: Server: Knock! Knock! Who's there? Client: Who's there? Server: Turnip Turnip who? Client: Turnip who? Server: Turnip the heat, it's cold in here! Want another? (y/n) If you want to hear another joke, type y; if not, type n. If you type y, the server begins again with "Knock! Knock!" If you type n, the server says "Bye." thus causing both the client and the server to exit.

If at any point you make a typing mistake, the KnockKnockServer object catches it and the server responds with a message similar to this: Server: You're supposed to say "Who's there?"! The server then starts the joke over again: Server: Try again. Knock! Knock! Note that the KnockKnockProtocol object is particular about spelling and punctuation but not about capitalization. Supporting Multiple Clients To keep the KnockKnockServer example simple, we designed it to listen for and handle a single connection request. However, multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads - one thread per each client connection. The basic flow of logic in such a server is this: while (true) { accept a connection ; create a thread to deal with the client ; end while The thread reads from and writes to the client connection as necessary. Try This: Modify the KnockKnockServer so that it can service multiple clients at the same time. Two classes compose our solution: KKMultiServer and KKMultiServerThread. KKMultiServer loops forever, listening for client connection requests on a ServerSocket. When a request comes in, KKMultiServer accepts the connection, creates a new KKMultiServerThread object to process it, hands it the socket returned from accept, and starts the thread. Then the server goes back to listening for connection requests. The KKMultiServerThread object communicates to the client by reading from and writing to the socket. Run the new Knock Knock server and then run several clients in succession. Lesson: All About Datagrams Some applications that you write to communicate over the network will not require the reliable, point-to-point channel provided by TCP. Rather, your applications might benefit from a mode of communication that delivers independent packages of information whose arrival and order of arrival are not guaranteed. The UDP protocol provides a mode of network communication whereby applications send packets of data, called datagrams, to one another. A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are

not guaranteed. The DatagramPacket and DatagramSocket classes in the java.net package implement system-independent datagram communication using UDP. What Is a Datagram? A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed. Writing a Datagram Client and Server This section walks you through an example that contains two Java programs that use datagrams to communicate. The server side is a quote server that listens to its DatagramSocket and sends a quotation to a client whenever the client requests it. The client side is a simple program that simply makes a request of the server. Broadcasting to Multiple Recipients This section modifies the quote server so that instead of sending a quotation to a single client upon request, the quote server broadcasts a quote every minute to as many clients as are listening. The client program must be modified accordingly. Note: Many firewalls and routers are configured not to allow UDP packets. If you have trouble connecting to a service outside your firewall, or if clients have trouble connecting to your service, ask your system administrator if UDP is permitted. What Is a Datagram? Clients and servers that communicate via a reliable channel, such as a TCP socket, have a dedicated point-to-point channel between themselves, or at least the illusion of one. To communicate, they establish a connection, transmit the data, and then close the connection. All data sent over the channel is received in the same order in which it was sent. This is guaranteed by the channel. In contrast, applications that communicate via datagrams send and receive completely independent packets of information. These clients and servers do not have and do not need a dedicated point-to-point channel. The delivery of datagrams to their destinations is not guaranteed. Nor is the order of their arrival. Definition: A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed. The java.net package contains three classes to help you write Java programs that use datagrams to send and receive packets over the network: DatagramSocket, DatagramPacket, and MulticastSocketAn application can send and receive DatagramPackets through a DatagramSocket. In addition, DatagramPackets can be broadcast to multiple recipients all listening to a MulticastSocket. Writing a Datagram Client and Server

The example featured in this section consists of two applications: a client and a server. The server continuously receives datagram packets over a datagram socket. Each datagram packet received by the server indicates a client request for a quotation. When the server receives a datagram, it replies by sending a datagram packet that contains a one-line "quote of the moment" back to the client. The client application in this example is fairly simple. It sends a single datagram packet to the server indicating that the client would like to receive a quote of the moment. The client then waits for the server to send a datagram packet in response. Two classes implement the server application: QuoteServer and QuoteServerThread. A single class implements the client application: QuoteClient. Let's investigate these classes, starting with the class that contains the main method for the server application. Working with a Server-Side Application contains an applet version of the QuoteClient class. The QuoteServer Class The QuoteServer class, shown here in its entirety, contains a single method: the main method for the quote server application. The main method simply creates a new QuoteServerThread object and starts it: import java.io.*; public class QuoteServer { public static void main(String[] args) throws IOException { new QuoteServerThread().start(); } } The QuoteServerThread class implements the main logic of the quote server. The QuoteServerThread Class When created, the QuoteServerThread creates a DatagramSocket on port 4445 (arbitrarily chosen). This is the DatagramSocket through which the server communicates with all of its clients. public QuoteServerThread() throws IOException { this("QuoteServer"); } public QuoteServerThread(String name) throws IOException { super(name); socket = new DatagramSocket(4445); try { in = new BufferedReader(

new FileReader("one-liners.txt")); } catch (FileNotFoundException e) System.err.println("Couldn't open quote file. " + "Serving time instead."); } } Remember that certain ports are dedicated to well-known services and you cannot use them. If you specify a port that is in use, the creation of the DatagramSocket will fail. The constructor also opens a BufferedReader on a file named one-liners.txt which contains a list of quotes. Each quote in the file is on a line by itself. Now for the interesting part of the QuoteServerThread: its run method. The run method overrides run in the Thread class and provides the implementation for the thread. For information about threads, see Defining and Starting a Thread. The run method contains a while loop that continues as long as there are more quotes in the file. During each iteration of the loop, the thread waits for a DatagramPacket to arrive over the DatagramSocket. The packet indicates a request from a client. In response to the client's request, the QuoteServerThread gets a quote from the file, puts it in a DatagramPacket and sends it over the DatagramSocket to the client that asked for it. Let's look first at the section that receives the requests from clients: byte[] buf = new byte[256]; DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet); The first statement creates an array of bytes which is then used to create a DatagramPacket. The DatagramPacket will be used to receive a datagram from the socket because of the constructor used to create it. This constructor requires only two arguments: a byte array that contains client-specific data and the length of the byte array. When constructing a DatagramPacket to send over the DatagramSocket, you also must supply the Internet address and port number of the packet's destination. You'll see this later when we discuss how the server responds to a client request. The last statement in the previous code snippet receives a datagram from the socket (the information received from the client gets copied into the packet). The receive method waits forever until a packet is received. If no packet is received, the server makes no further progress and just waits. Now assume that, the server has received a request from a client for a quote. Now the server must respond. This section of code in the run method constructs the response: String dString = null; if (in == null)

dString = new Date().toString(); else dString = getNextQuote(); buf = dString.getBytes(); If the quote file did not get opened for some reason, then in equals null. If this is the case, the quote server serves up the time of day instead. Otherwise, the quote server gets the next quote from the already opened file. Finally, the code converts the string to an array of bytes. Now, the run method sends the response to the client over the DatagramSocket with this code: InetAddress address = packet.getAddress(); int port = packet.getPort(); packet = new DatagramPacket(buf, buf.length, address, port); socket.send(packet); The first two statements in this code segment get the Internet address and the port number, respectively, from the datagram packet received from the client. The Internet address and port number indicate where the datagram packet came from. This is where the server must send its response. In this example, the byte array of the datagram packet contains no relevant information. The arrival of the packet itself indicates a request from a client that can be found at the Internet address and port number indicated in the datagram packet. The third statement creates a new DatagramPacket object intended for sending a datagram message over the datagram socket. You can tell that the new DatagramPacket is intended to send data over the socket because of the constructor used to create it. This constructor requires four arguments. The first two arguments are the same required by the constructor used to create receiving datagrams: a byte array containing the message from the sender to the receiver and the length of this array. The next two arguments are different: an Internet address and a port number. These two arguments are the complete address of the destination of the datagram packet and must be supplied by the sender of the datagram. The last line of code sends the DatagramPacket on its way. When the server has read all the quotes from the quote file, the while loop terminates and the run method cleans up: socket.close(); The QuoteClient Class The QuoteClient class implements a client application for the QuoteServer. This application sends a request to the QuoteServer, waits for the response, and, when the response is received, displays it to the standard output. Let's look at the code in detail.

The QuoteClient class contains one method, the main method for the client application. The top of the main method declares several local variables for its use: int port; InetAddress address; DatagramSocket socket = null; DatagramPacket packet; byte[] sendBuf = new byte[256]; First, the main method processes the command-line arguments used to invoke the QuoteClient application: if (args.length != 1) { System.out.println("Usage: java QuoteClient <hostname>"); return; } The QuoteClient application requires one command-line arguments: the name of the machine on which the QuoteServer is running. Next, the main method creates a DatagramSocket: DatagramSocket socket = new DatagramSocket(); The client uses a constructor that does not require a port number. This constructor just binds the DatagramSocket to any available local port. It doesn't matter what port the client is bound to because the DatagramPackets contain the addressing information. The server gets the port number from the DatagramPackets and send its response to that port. Next, the QuoteClient program sends a request to the server: byte[] buf = new byte[256]; InetAddress address = InetAddress.getByName(args[0]); DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445); socket.send(packet); The code segment gets the Internet address for the host named on the command line (presumably the name of the machine on which the server is running). This InetAddress and the port number 4445 (the port number that the server used to create its DatagramSocket) are then used to create DatagramPacket destined for that Internet address and port number. Therefore the DatagramPacket will be delivered to the quote server. Note that the code creates a DatagramPacket with an empty byte array. The byte array is empty because this datagram packet is simply a request to the server for information. All the server needs to know to send a response--the address and port number to which reply--is automatically part of the packet. Next, the client gets a response from the server and displays it:

packet = new DatagramPacket(buf, buf.length); socket.receive(packet); String received = new String(packet.getData(), 0, packet.getLength()); System.out.println("Quote of the Moment: " + received); To get a response from the server, the client creates a "receive" packet and uses the DatagramSocket receive method to receive the reply from the server. The receive method waits until a datagram packet destined for the client comes through the socket. Note that if the server's reply is somehow lost, the client will wait forever because of the noguarantee policy of the datagram model. Normally, a client sets a timer so that it doesn't wait forever for a reply; if no reply arrives, the timer goes off and the client retransmits. When the client receives a reply from the server, the client uses the getData method to retrieve that data from the packet. The client then converts the data to a string and displays it. Running the Server and Client After you've successfully compiled the server and the client programs, you run them. You have to run the server program first. Just use the Java interpreter and specify the QuoteServer class name. Once the server has started, you can run the client program. Remember to run the client program with one command-line argument: the name of the host on which the QuoteServer is running. After the client sends a request and receives a response from the server, you should see output similar to this: Quote of the Moment: Good programming is 99% sweat and 1% coffee. Broadcasting to Multiple Recipients In addition to DatagramSocket, which lets programs send packets to one another, java.net includes a class called MulticastSocket. This kind of socket is used on the client-side to listen for packets that the server broadcasts to multiple clients. Let's rewrite the quote server so that it broadcasts DatagramPackets to multiple recipients. Instead of sending quotes to a specific client that makes a request, the new server now needs to broadcast quotes at a regular interval. The client needs to be modified so that it passively listens for quotes and does so on a MulticastSocket. This example is comprised of three classes which are modifications of the three classes from the previous example: MulticastServer, MulticastServerThread, and MulticastClient. This discussion highlights the interesting parts of these classes. Here is the new version of the server's main program. The differences between this code and the previous version, QuoteServer, are shown in bold:

import java.io.*; public class MulticastServer { public static void main(String[] args) throws IOException { new MulticastServerThread().start(); } } Basically, the server got a new name and creates a MulticastServerThread instead of a QuoteServerThread. Now let's look at the MulticastServerThread which contains the heart of the server. Here's its class declaration: public class MulticastServerThread extends QuoteServerThread { ... } We've made this class a subclass of QuoteServerThread so that it can use the constructor, and inherit some member variable and the getNextQuote method. Recall that QuoteServerThread creates a DatagramSocket bound to port 4445 and opens the quote file. The DatagramSocket's port number doesn't actually matter in this example because the client never send anything to the server. The only method explicitly implemented in MulticastServerThread is its run method. The differences between this run method and the one in QuoteServerThread are shown in bold: public void run() { while (moreQuotes) { try { byte[] buf new byte[256]; // don't wait for request...just send a quote String dString = null; if (in == null) dString = new Date().toString(); else dString = getNextQuote(); buf = dString.getBytes(); InetAddress group = InetAddress.getByName( "230.0.0.1"); DatagramPacket packet; packet = new DatagramPacket(buf, buf.length, group, 4446); socket.send(packet); try { sleep((long)Math.random() * FIVE_SECONDS); } catch (InterruptedException e) { } } catch (IOException e) {

e.printStackTrace(); moreQuotes = false; } } socket.close(); } The interesting change is how the DatagramPacket is constructed, in particular, the InetAddress and port used to construct the DatagramPacket. Recall that the previous example retrieved the InetAddress and port number from the packet sent to the server from the client. This was because the server needed to reply directly to the client. Now, the server needs to address multiple clients. So this time both the InetAddress and the port number are hard-coded. The hard-coded port number is 4446 (the client must have a MulticastSocket bound to this port). The hard-coded InetAddress of the DatagramPacket is "230.0.0.1" and is a group identifier (rather than the Internet address of the machine on which a single client is running). This particular address was arbitrarily chosen from the reserved for this purpose. Created in this way, the DatagramPacket is destined for all clients listening to port number 4446 who are member of the "230.0.0.1" group. To listen to port number 4446, the new client program just created its MulticastSocket with that port number. To become a member of the "230.0.0.1" group, the client calls the MulticastSocket's joinGroup method with the InetAddress that identifies the group. Now, the client is set up to receive DatagramPackets destined for the port and group specified. Here's the relevant code from the new client program (which was also rewritten to passively receive quotes rather than actively request them). The bold statements are the ones that interact with the MulticastSocket: MulticastSocket socket = new MulticastSocket(4446); InetAddress group = InetAddress.getByName("230.0.0.1"); socket.joinGroup(group); DatagramPacket packet; for (int i = 0; i < 5; i++) { byte[] buf = new byte[256]; packet = new DatagramPacket(buf, buf.length); socket.receive(packet); String received = new String(packet.getData()); System.out.println("Quote of the Moment: " + received); } socket.leaveGroup(group); socket.close();

Notice that the server uses a DatagramSocket to broadcast packet received by the client over a MulticastSocket. Alternatively, it could have used a MulticastSocket. The socket used by the server to send the DatagramPacket is not important. What's important when broadcasting packets is the addressing information contained in the DatagramPacket, and the socket used by the client to listen for it Try this: Run the MulticastServer and several clients. Watch how the clients all get the same quotes.

Potrebbero piacerti anche