1. OSI Model To The TCP/IP Model
www.thebryantadvantage.com OSI TCPIP Model Mapping
The four layers of the TCP/IP architecture can be compared to certain levels of the OSI model. It’s important to know what each level of the TCP/IP protocol architecture does, and how these layers map to the OSI model.
http://www.roseindia.net/technology/networking/osi.shtml
2. Custom Networking in Java
(http://download.oracle.com/javase/tutorial/networking/index.html)
The Java platform is highly regarded in part because of its suitability for writing programs that use and interact with the resources on the Internet and the World Wide Web. In fact, Java-compatible browsers use this ability of the Java platform to the extreme to transport and run applets over the Internet.
This trail walks you through the complexities of writing Java applications and applets that can be used on the Internet.
Overview of Networking has two sections. The first describes the networking capabilities of the Java platform that you may already be using without realizing that you are using the network. The second provides a brief overview of networking to familiarize you with terms and concepts that you should understand before reading how to use URLs, sockets, and datagrams.
Working With URLs discusses how your Java programs can use URLs to access information on the Internet. A URL (Uniform Resource Locator) is the address of a resource on the Internet. Your Java programs can use URLs to connect to and retrieve information over a network. This lesson provides a more complete definition of a URL and shows you how to create and parse a URL, how to open a connection to a URL, and how to read from and write to that connection.
All About Sockets explains how to use sockets so that your programs can communicate with other programs on the network. A socket is one endpoint of a two-way communication link between two programs running on the network. This lesson shows you how a client can connect to a standard server, the Echo server, and communicate with it via a socket. It then walks you through the details of a complete client/server example, which shows you how to implement both the client side and the server side of a client/server pair.
All About Datagrams takes you step by step through a simple client/server example that uses datagrams to communicate. It then challenges you to rewrite the example using multicast socket instead.
Programmatic Access to Network Parameters explains why you might want to access network interface parameters and how to do so. It gives examples of how to list all the IP addresses assigned to the machine as well as other useful information such as whether the interface is running.
Working With Cookies discusses how cookies are used to create a session between a client and server, and how you can take advantage of cookies in your HTTP URL connections.
Trước hểt review lại mô hình client server với socket (TCP/IP Chat Application Using C#)
The
www.thebryantadvantage.com OSI TCPIP Model Mapping
The Application Layer of the TCP/IP model performs much the same tasks as the Application, Presentation, and Session layers of the OSI model.
The Transport layer in the TCP/IP architecture is similar to the Transport layer in the OSI model. This layer can use TCP or UDP as well.
The Internetwork layer in the TCP/IP architecture uses IP addresses to determine how packets should be routed. Remember that the OSI model uses IP addresses, or “Layer 3 Addresses”, at the Network layer. The two layers do much the same thing. This layer is also referred to in the TCP/IP model as the Internet layer.
The Network Interface layer in the TCP/IP architecture serves to define the protocols and the hardware needed to actually deliver the data across the network. The Network Interface model does the work of both the Data Link and Physical Layers in the OSI model.
http://www.roseindia.net/technology/networking/osi.shtml
The OSI Model is used to describe networks and network application.
Layers of OSI Model
Three are Sever Layers of OSI Model :
OSI Layer Diagram:
7) Application Layer : The application layer provider different services to the application. Example of services provided by this layer are file transfer, electronic messaging e-mail, virtual terminal access and network management.
6) Presentation Layer : The Presentation layer is responsible for protocol conversion, date encryption/decryption, Expanding graphics command and the date compression. This layer makes the communications between two host possible.
5) Session Layer : This layer is responsible for establishing the process-to-process communication between the host in the network. This layer is responsible for establishing and ending the sessions across the network. The interactive login is an example of services provided by this layer in which the connective are re-connected in care of any interruption.
4) Transport Layer : This layer is responsible for end-to-end delivers of messages between the networked hosts. It first divides the streams of data into chunks or packets before transmission and then the receiving computer re-assembles the packets. It also guarantee error free data delivery without loss or duplications.
3) Network Layer : This layer is responsible for translating the logical network address and names into their physical address ( MAC address). This layer is also responsible for addressing, determining routes for sending and managing network problems such as packet switching, data congestion and routines.
2) Data Link Layer : Data link layer is responsible for controlling the error between adjacent nodes and transfer the frames to other computer via physical layer. Data link layer is used by hubs and switches for their operation.
1) Physical Layer : Physical Layer is responsible for transmitting row bit stream over the physical cable. The physical layer defines the hardware items such as cables, cards, voltages etc.
How to remember the layer of OSI model?
The easiest way to remember the different layers of OSI Model is to use the mnemonic "All people seem To need Data Processing":
Layer | Name | |
Mnemonic | ||
7 | Application | All |
6 | Presentation | People |
5 | Session | Seem |
4 | Transport | To |
3 | Network | Need |
2 | Data Link | Data |
1 | Physical | Processing |
2. Custom Networking in Java
(http://download.oracle.com/javase/tutorial/networking/index.html)
The Java platform is highly regarded in part because of its suitability for writing programs that use and interact with the resources on the Internet and the World Wide Web. In fact, Java-compatible browsers use this ability of the Java platform to the extreme to transport and run applets over the Internet.
This trail walks you through the complexities of writing Java applications and applets that can be used on the Internet.
Overview of Networking has two sections. The first describes the networking capabilities of the Java platform that you may already be using without realizing that you are using the network. The second provides a brief overview of networking to familiarize you with terms and concepts that you should understand before reading how to use URLs, sockets, and datagrams.
Working With URLs discusses how your Java programs can use URLs to access information on the Internet. A URL (Uniform Resource Locator) is the address of a resource on the Internet. Your Java programs can use URLs to connect to and retrieve information over a network. This lesson provides a more complete definition of a URL and shows you how to create and parse a URL, how to open a connection to a URL, and how to read from and write to that connection.
All About Sockets explains how to use sockets so that your programs can communicate with other programs on the network. A socket is one endpoint of a two-way communication link between two programs running on the network. This lesson shows you how a client can connect to a standard server, the Echo server, and communicate with it via a socket. It then walks you through the details of a complete client/server example, which shows you how to implement both the client side and the server side of a client/server pair.
All About Datagrams takes you step by step through a simple client/server example that uses datagrams to communicate. It then challenges you to rewrite the example using multicast socket instead.
Programmatic Access to Network Parameters explains why you might want to access network interface parameters and how to do so. It gives examples of how to list all the IP addresses assigned to the machine as well as other useful information such as whether the interface is running.
Working With Cookies discusses how cookies are used to create a session between a client and server, and how you can take advantage of cookies in your HTTP URL connections.
Trước hểt review lại mô hình client server với socket (TCP/IP Chat Application Using C#)
Security considerations: Note that communications over the network are subject to approval by the current security manager. The Security Manager describes what a security manager is and how it impacts your applications. For general information about the security features provided by the JDK, refer to Security Features in Java SE.The example programs in the following lessons that cover URLs, sockets, and datagrams are standalone applications, which, by default, have no security manager. If you convert these applications to applets, they may be unable to communicate over the network, depending on the browser or viewer in which they are running. See What Applets Can and Cannot Do for information about the security restrictions placed on applets.
Lesson: Overview of Networking
Before plowing through the examples in the next several lessons, you should have an understanding of some networking basics. Also, to boost your confidence, we've included a section that reviews what you may already know about networking in Java without even realizing it.
What You May Already Know About Networking in Java
If you've been working on the other trails in this tutorial, you've probably loaded an applet over the Internet by now, and you've likely loaded images from the network into applets running over the network. All of this is using the network and you already know how to do it. This page highlights the networking features that are covered in other trails and lessons of this tutorial--features that you might already be familiar with--and provides links to the pages that discuss those features.Networking Basics
You'll learn what you need to know about TCP, UDP, sockets, datagrams, and ports to get the most out of the remaining lessons in this trail. If you are already familiar with these concepts, feel free to skip this section.
What You May Already Know About Networking in Java
The word networking strikes fear in the hearts of many programmers. Fear not! Using the networking capabilities provided in the Java environment is quite easy. In fact, you may be using the network already without even realizing it!
Loading Applets from the Network
If you have access to a Java-enabled browser, you have undoubtedly already executed many applets. The applets you've run are referenced by a special tag in an HTML file — the<APPLET>
tag. Applets can be located anywhere, whether on your local machine or somewhere out on the Internet. The location of the applet is completely invisible to you, the user. However, the location of the applet is encoded within the<APPLET>
tag. The browser decodes this information, locates the applet, and runs it. If the applet is on some machine other than your own, the browser must download the applet before it can be run.This is the highest level of access that you have to the Internet from the Java development environment. Someone else has taken the time to write a browser that does all of the grunt work of connecting to the network and getting data from it, thereby enabling you to run applets from anywhere in the world.
For more information:
The "Hello World!" Application shows you how to write your first applet and run it.
The Applets trail describes how to write Java applets from A to Z.
Loading Images from URLs
If you've ventured into writing your own Java applets and applications, you may have run into a class in the java.net package called URL. This class represents a Uniform Resource Locator and is the address of some resource on the network. Your applets and applications can use a URL to reference and even connect to resources out on the network. For example, to load an image from the network, your Java program must first create a URL that contains the address to the image.This is the next highest level of interaction you can have with the Internet — your Java program gets an address of something it wants, creates a URL for it, and then uses some existing function in the Java development environment that does the grunt work of connecting to the network and retrieving the resource.
For more information:
How to Use Icons shows you how to load an image into your Java program (whether applets or applications) when you have its URL. Before you can load the image you must create a URL object with the address of the resource in it.
Working with URLs, the next lesson in this trail, provides a complete discussion about URLs, including how your programs can connect to them and read from and write to that connection.
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 thejava.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.
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.
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.
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-of-order 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:
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:
Definition: The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer.
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 well-known 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 injava.net
, Java programs can use TCP or UDP to communicate over the Internet. TheURL
,URLConnection
,Socket
, andServerSocket
classes all use TCP to communicate over the network. TheDatagramPacket
,DatagramSocket
, andMulticastSocket
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 calledURL
in thejava.net
package to represent a URL address.
Terminology Note: The term URL can be ambiguous. It can refer to an Internet address or aURL
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 theURL
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 theopenStream()
method.Connecting to a URL
If you want to do more than just read from a URL, you can connect to it by callingopenConnection()
on the URL. TheopenConnection()
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.
The following is an example of a URL which addresses the
Definition: URL is an acronym for Uniform Resource Locator and is a reference (an address) to a resource on the Internet.
java.sun.com
website:
As in the previous diagram, a URL has two main components:
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:
- Protocol identifier
- Resource name
Host Name The name of the machine on which the resource lives. Filename The pathname to the file on the machine. Port Number The port number to which to connect (typically optional). Reference 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 sitejava.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 aURL
object is from aString
that represents the human-readable 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:
In your Java program, you can use ahttp://www.gamelan.com/String
containing this text to create aURL
object:
TheURL gamelan = new URL("http://www.gamelan.com/");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 createURL
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 calledJoesHomePage.html
. Within this page, are links to other pages,PicturesOfMe.html
andMyKids.html
, that are on the same machine and in the same directory asJoesHomePage.html
. The links toPicturesOfMe.html
andMyKids.html
fromJoesHomePage.html
could be specified just as filenames, like this:
These URL addresses are relative URLs. That is, the URLs are specified relative to the file in which they are contained--<a href="PicturesOfMe.html">Pictures of Me</a> <a href="MyKids.html">Pictures of My Kids</a>JoesHomePage.html
.In your Java programs, you can create aURL
object from a relative URL specification. For example, suppose you know two URLs at the Gamelan site:
You can createhttp://www.gamelan.com/pages/Gamelan.game.html http://www.gamelan.com/pages/Gamelan.net.htmlURL
objects for these pages relative to their common base URL:http://www.gamelan.com/pages/
like this:
This code snippet uses theURL gamelan = new URL("http://www.gamelan.com/pages/"); URL gamelanGames = new URL(gamelan, "Gamelan.game.html"); URL gamelanNetwork = new URL(gamelan, "Gamelan.net.html");URL
constructor that lets you create aURL
object from anotherURL
object (the base) and a relative URL specification. The general form of this constructor is:
The first argument is aURL(URL baseURL, String relativeURL)URL
object that specifies the base of the newURL
. The second argument is aString
that specifies the rest of the resource name relative to the base. IfbaseURL
is null, then this constructor treatsrelativeURL
like an absolute URL specification. Conversely, ifrelativeURL
is an absolute URL specification, then the constructor ignoresbaseURL
.This constructor is also useful for creatingURL
objects for named anchors (also called references) within a file. For example, suppose theGamelan.network.html
file has a named anchor calledBOTTOM
at the bottom of the file. You can use the relative URL constructor to create aURL
object for it like this:
URL gamelanNetworkBottom = new URL(gamelanNetwork, "#BOTTOM");
Other URL Constructors
TheURL
class provides two additional constructors for creating aURL
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 aURL
from the panel's components. The first constructor creates aURL
object from a protocol, host name, and filename. The following code snippet creates aURL
to theGamelan.net.html
file at the Gamelan site:
This is equivalent tonew 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 finalnew URL("http://www.gamelan.com/pages/Gamelan.net.html");URL
constructor adds the port number to the list of arguments used in the previous constructor:
This creates aURL gamelan = new URL("http", "www.gamelan.com", 80, "pages/Gamelan.network.html");URL
object for the following URL:
If you construct ahttp://www.gamelan.com:80/pages/Gamelan.network.htmlURL
object using one of these constructors, you can get aString
containing the complete URL address by using theURL
object'stoString
method or the equivalenttoExternalForm
method.
URL addresses with Special characters
Some URL addresses contain special characters, for example the space character. Like this:
To make theses characters legal they need to encoded before passing them to the URL constructor.http://foo.com/hello world/
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 theURL url = new URL("http://foo.com/hello%20world");java.net.URI
class to automatically take care of the encoding for you.
And then convert the URI to a URL.URI uri = new URI("http", "foo.com", "/hello world/", "");
URL url = uri.toURL();
MalformedURLException
Each of the fourURL
constructors throws aMalformedURLException
if the arguments to the constructor refer to anull
or unknown protocol. Typically, you want to catch and handle this exception by embedding your URL constructor statements in atry
/catch
pair, like this:
See Exceptions for information about handling exceptions.try { URL myURL = new URL(. . .) } catch (MalformedURLException e) { . . . // exception handler code here . . . }
Note:URL
s are "write-once" objects. Once you've created aURL
object, you cannot change any of its attributes (protocol, host name, filename, or port number).
Parsing a URL
TheURL
class provides several methods that let you queryURL
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 asgetPath
, plus the concatenation of the value ofgetQuery
, 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 aURL
, you can call theURL
'sopenStream()
method to get a stream from which you can read the contents of the URL. TheopenStream()
method returns ajava.io.InputStream
object, so reading from a URL is as easy as reading from an input stream.The following small Java program usesopenStream()
to get an input stream on the URLhttp://www.yahoo.com/
. It then opens aBufferedReader
on the input stream and reads from theBufferedReader
thereby reading from the URL. Everything read is copied to the standard output stream:
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 atimport 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(); } }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 toset the proxy host so that the program can find the Yahoo server.
Connecting to a URL
After you've successfully created aURL
object, you can call theURL
object'sopenConnection
method to get aURLConnection
object, or one of its protocol specific subclasses, e.g.java.net.HttpURLConnection
You can use thisURLConnection
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 theURLConnection.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:
A newtry { 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 . . . }URLConnection
object is created every time by calling theopenConnection
method of the protocol handler for this URL.You are not always required to explicitly call theconnect
method to initiate the connection. Operations that depend on being connected, likegetInputStream
,getOutputStream
, etc, will implicitly perform the connection, if necessary.
Now that you've successfully connected to your URL, you can use theURLConnection
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
TheURLConnection
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 theURLReader
program shown in Reading Directly from a URL.However, rather than getting an input stream directly from the URL, this program explicitly retrieves aURLConnection
object and gets an input stream from the connection. The connection is opened implicitly by callinggetInputStream
. Then, likeURLReader
, this program creates aBufferedReader
on the input stream and reads from it. The bold statements highlight the differences between this example and the previous
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 aimport 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(); } }URLConnection
instead of reading directly from a URL might be more useful. This is because you can use theURLConnection
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:
Here is a small
- Create a
URL
.- 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.
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 formstring=string_to_reverse
, wherestring_to_reverse
is the string whose characters you want displayed in reverse order.
Here's an example program that runs theReverseServlet
over the network through aURLConnection
:
Let's examine the program and see how it works. First, the program processes its command-line arguments: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(); } }
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 theif (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");ReverseServlet
and the string that will be reversed. It may contain spaces or other non-alphanumeric characters. These characters must be encoded because the string is processed on its way to the server. TheURLEncoder
class methods encode the characters.Next, the program creates theURL
object, and sets the connection so that it can write to it:
The program then creates an output stream on the connection and opens anURL url = new URL(args[0]); URLConnection connection = url.openConnection(); connection.setDoOutput(true);OutputStreamWriter
on it:
If the URL does not support output,OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());getOutputStream
method throws anUnknownServiceException
. 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:
This code writes to the output stream using theout.write("string=" + stringToReverse); out.close();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. TheReverse
program constructs the input in the form required by the script by prependingstring=
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. TheReverse
program does it like this:
If yourBufferedReader in = new BufferedReader( new InputStreamReader( connection.getInputStream())); String decodedString; while ((decodedString = in.readLine()) != null) { System.out.println(decodedString); } in.close();ReverseServlet
is located athttp://foobar.com/servlet/ReverseServlet
, then when you run theReverse
program using
as the argument (including the double quote marks), you should see this output:http://foobar.com/servlet/ReverseServlet "Reverse Me"
Reverse Me reversed is: eM esreveR
Lesson: All About Sockets
URL
s andURLConnection
s 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.
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.
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.
Thejava.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. TheSocket
class sits on top of a platform-dependent implementation, hiding the details of any particular system from your Java program. By using thejava.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 theServerSocket
class, which implements a socket that servers can use to listen for and accept connections to clients. This lesson shows you how to use theSocket
andServerSocket
classes.
If you are trying to connect to the Web, theURL
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 theSocket
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:
Note thatimport 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(); } }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 thetry
block of themain
method are critical. These lines establish the socket connection between the client and the server and open aPrintWriter
and aBufferedReader
on the socket:
The first statement in this sequence creates a newechoSocket = new Socket("taranis", 7); out = new PrintWriter(echoSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( echoSocket.getInputStream()));Socket
object and names itechoSocket
. TheSocket
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 nametaranis
. 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 aPrintWriter
on it. Similarly, the third statement gets the socket's input stream and opens aBufferedReader
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 thePrintWriter
. To get the server's response,EchoClient
reads from theBufferedReader
. 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 thewhile
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 thePrintWriter
connected to the socket:
The last statement in theString userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); }while
loop reads a line of information from theBufferedReader
connected to the socket. ThereadLine
method waits until the server echoes the information back toEchoClient
. Whenreadline
returns,EchoClient
prints the information to the standard output.Thewhile
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. Thewhile
loop then terminates and the program continues, executing the next four lines of code:
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:out.close(); in.close(); stdIn.close(); echoSocket.close();
Only step 3 differs from client to client, depending on the server. The other steps remain largely the same.
- 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.
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 theEchoClient
example from the previous section. The server program is implemented by two classes:KnockKnockServer
andKnockKnockProtocol
,KnockKnockServer
contains themain
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 theKnockKnockServer
class.The server program begins by creating a newServerSocket
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 ajava.net
class that provides a system-independent implementation of the server side of a client/server socket connection. The constructor forServerSocket
throws an exception if it can't listen on the specified port (for example, the port is already being used). In this case, theKnockKnockServer
has no choice but to exit.If the server successfully binds to its port, then theServerSocket
object is successfully created and the server continues to the next step--accepting a connection from a client (shown in bold):
TheSocket clientSocket = null; try { clientSocket = serverSocket.accept(); } catch (IOException e) { System.out.println("Accept failed: 4444"); System.exit(-1); }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 newSocket
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 newSocket
and continue to listen for client connection requests on the originalServerSocket
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:
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; }
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
- Gets the socket's input and output stream and opens readers and writers on them.
- Initiates communication with the client by writing to the socket (shown in bold).
- Communicates with the client by reading from and writing to the socket (the
while
loop).KnockKnockProtocol
object-the object that keeps track of the current joke, the current state within the joke, and so on.After theKnockKnockProtocol
is created, the code callsKnockKnockProtocol
'sprocessInput
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 thePrintWriter
connected to the client socket, thereby sending the message to the client.
Step 3 is encoded in thewhile
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 theKnockKnockProtocol
object and asks theKnockKnockProtocol
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 theKnockKnockServer
object is "Bye." this indicates that the client doesn't want any more jokes and the loop quits.
TheKnockKnockServer
class is a well-behaved server, so the last several lines of this section ofKnockKnockServer
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
TheKnockKnockProtocol
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. TheKnockKnockServer
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
TheKnockKnockClient
class implements the client program that speaks to theKnockKnockServer
.KnockKnockClient
is based on theEchoClient
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:
When creating its socket,kkSocket = new Socket("taranis", 4444); out = new PrintWriter(kkSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( kkSocket.getInputStream()));KnockKnockClient
uses the host nametaranis
, 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 theKnockKnockServer
.TheKnockKnockClient
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 whichKnockKnockServer
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.
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: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); } }
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 theKnockKnockClient
program, you will see the following error message:
To fix this, modify theDon't know about host: taranisKnockKnockClient
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:
Now, you must respond with:Server: Knock! Knock!
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):Who's there?
Now, you respond with:Server: Knock! Knock! Who's there? Client: Who's there? Server: Turnip
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:Turnip who?"
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, theServer: 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)KnockKnockServer
object catches it and the server responds with a message similar to this:
The server then starts the joke over again:Server: You're supposed to say "Who's there?"!
Note that theServer: Try again. Knock! Knock!KnockKnockProtocol
object is particular about spelling and punctuation but not about capitalization.
Supporting Multiple Clients
To keep theKnockKnockServer
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 sameServerSocket
. 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:
The thread reads from and writes to the client connection as necessary.while (true) { accept a connection ; create a thread to deal with the client ; end while
Try This: Modify theKnockKnockServer
so that it can service multiple clients at the same time. Two classes compose our solution:KKMultiServer
andKKMultiServerThread
.KKMultiServer
loops forever, listening for client connection requests on aServerSocket
. When a request comes in,KKMultiServer
accepts the connection, creates a newKKMultiServerThread
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. TheKKMultiServerThread
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. TheDatagramPacket
andDatagramSocket
classes in thejava.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 itsDatagramSocket
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.
The
Definition: A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.
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
, andMulticastSocket
An application can send and receiveDatagramPacket
s through aDatagramSocket
. In addition,DatagramPacket
s can be broadcast to multiple recipients all listening to aMulticastSocket
.
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
andQuoteServerThread
. A single class implements the client application:QuoteClient
.
Let's investigate these classes, starting with the class that contains themain
method for the server application. Working With a Server-Side Application contains an applet version of theQuoteClient
class.
The QuoteServer Class
TheQuoteServer
class, shown here in its entirety, contains a single method: themain
method for the quote server application. Themain
method simply creates a newQuoteServerThread
object and starts it:
Theimport java.io.*; public class QuoteServer { public static void main(String[] args) throws IOException { new QuoteServerThread().start(); } }QuoteServerThread
class implements the main logic of the quote server.
The QuoteServerThread
Class
When created, theQuoteServerThread
creates aDatagramSocket
on port 4445 (arbitrarily chosen). This is theDatagramSocket
through which the server communicates with all of its clients.
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 thepublic 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."); } }DatagramSocket
will fail.The constructor also opens aBufferedReader
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 theQuoteServerThread
: itsrun
method. Therun
method overridesrun
in theThread
class and provides the implementation for the thread. For information about threads, see Defining and Starting a Thread.
Therun
method contains awhile
loop that continues as long as there are more quotes in the file. During each iteration of the loop, the thread waits for aDatagramPacket
to arrive over theDatagramSocket
. The packet indicates a request from a client. In response to the client's request, theQuoteServerThread
gets a quote from the file, puts it in aDatagramPacket
and sends it over theDatagramSocket
to the client that asked for it.
Let's look first at the section that receives the requests from clients:
The first statement creates an array of bytes which is then used to create abyte[] buf = new byte[256]; DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet);DatagramPacket
. TheDatagramPacket
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 aDatagramPacket
to send over theDatagramSocket
, 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:
If the quote file did not get opened for some reason, thenString dString = null; if (in == null) dString = new Date().toString(); else dString = getNextQuote(); buf = dString.getBytes();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, therun
method sends the response to the client over theDatagramSocket
with this code:
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 newInetAddress address = packet.getAddress(); int port = packet.getPort(); packet = new DatagramPacket(buf, buf.length, address, port); socket.send(packet);DatagramPacket
object intended for sending a datagram message over the datagram socket. You can tell that the newDatagramPacket
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 theDatagramPacket
on its way.
When the server has read all the quotes from the quote file, thewhile
loop terminates and therun
method cleans up:
socket.close();
The QuoteClient Class
TheQuoteClient
class implements a client application for theQuoteServer
. This application sends a request to theQuoteServer
, waits for the response, and, when the response is received, displays it to the standard output. Let's look at the code in detail.TheQuoteClient
class contains one method, themain
method for the client application. The top of themain
method declares several local variables for its use:
First, theint port; InetAddress address; DatagramSocket socket = null; DatagramPacket packet; byte[] sendBuf = new byte[256];main
method processes the command-line arguments used to invoke theQuoteClient
application:
Theif (args.length != 1) { System.out.println("Usage: java QuoteClient <hostname>"); return; }QuoteClient
application requires one command-line arguments: the name of the machine on which theQuoteServer
is running.Next, themain
method creates aDatagramSocket
:
The client uses a constructor that does not require a port number. This constructor just binds theDatagramSocket socket = new DatagramSocket();DatagramSocket
to any available local port. It doesn't matter what port the client is bound to because theDatagramPacket
s contain the addressing information. The server gets the port number from theDatagramPacket
s and send its response to that port.Next, theQuoteClient
program sends a request to the server:
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). Thisbyte[] buf = new byte[256]; InetAddress address = InetAddress.getByName(args[0]); DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445); socket.send(packet);InetAddress
and the port number 4445 (the port number that the server used to create itsDatagramSocket
) are then used to createDatagramPacket
destined for that Internet address and port number. Therefore theDatagramPacket
will be delivered to the quote server.Note that the code creates aDatagramPacket
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:
To get a response from the server, the client creates a "receive" packet and uses thepacket = 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);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 no-guarantee 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 theQuoteServer
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 theQuoteServer
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 toDatagramSocket
, which lets programs send packets to one another, java.net includes a class calledMulticastSocket
. 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 broadcastsDatagramPacket
s 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 aMulticastSocket
.
This example is comprised of three classes which are modifications of the three classes from the previous example:MulticastServer
,MulticastServerThread
, andMulticastClient
. 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:
Basically, the server got a new name and creates aimport java.io.*; public class MulticastServer { public static void main(String[] args) throws IOException { new MulticastServerThread().start(); } }MulticastServerThread
instead of aQuoteServerThread
. Now let's look at theMulticastServerThread
which contains the heart of the server. Here's its class declaration:
We've made this class a subclass ofpublic class MulticastServerThread extends QuoteServerThread { ... }QuoteServerThread
so that it can use the constructor, and inherit some member variable and thegetNextQuote
method. Recall thatQuoteServerThread
creates aDatagramSocket
bound to port 4445 and opens the quote file. TheDatagramSocket
's port number doesn't actually matter in this example because the client never send anything to the server.The only method explicitly implemented inMulticastServerThread
is itsrun
method. The differences between thisrun
method and the one inQuoteServerThread
are shown in bold:
The interesting change is how thepublic 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(); }DatagramPacket
is constructed, in particular, theInetAddress
and port used to construct theDatagramPacket
. Recall that the previous example retrieved theInetAddress
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 theInetAddress
and the port number are hard-coded.The hard-coded port number is 4446 (the client must have aMulticastSocket
bound to this port). The hard-codedInetAddress
of theDatagramPacket
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, theDatagramPacket
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 itsMulticastSocket
with that port number. To become a member of the "230.0.0.1" group, the client calls theMulticastSocket
'sjoinGroup
method with theInetAddress
that identifies the group. Now, the client is set up to receiveDatagramPacket
s 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 theMulticastSocket
:
Notice that the server uses aMulticastSocket 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();DatagramSocket
to broadcast packet received by the client over aMulticastSocket
. Alternatively, it could have used aMulticastSocket
. The socket used by the server to send theDatagramPacket
is not important. What's important when broadcasting packets is the addressing information contained in theDatagramPacket
, and the socket used by the client to listen for it
Try this: Run theMulticastServer
and several clients. Watch how the clients all get the same quotes.
Lesson: Programmatic Access to Network Parameters
Systems often run with multiple active network connections, such as wired Ethernet,802.11 b/g
(wireless), and bluetooth. Some applications might need to access this information to perform the particular network activity on a specific connection.Thejava.net.NetworkInterface
class provides access to this information.
This lesson guides you through some of the more common uses of this class and provides examples that list all the network interfaces on a machine as well as their IP addresses and status.
What Is a Network Interface?
This page describes a network interface and explains why you might want to use it.Retrieving Network Interfaces
This page contains an example that illustrates how a client program can retrieve all the network interfaces on a machine.Listing Network Interface Addresses
This page shows you how to list the IP addresses assigned to all the network interfaces on a machine.Network Interface Parameters
This page shows you how to determine whether a network interface is running or if the network interface is a loopback interface, a point-to-point interface, or a virtual interface. You can also learn how to determine if the interface supports multicasting.
What Is a Network Interface?
A network interface is the point of interconnection between a computer and a private or public network. A network interface is generally a network interface card (NIC), but does not have to have a physical form. Instead, the network interface can be implemented in software. For example, the loopback interface (127.0.0.1 for IPv4 and ::1 for IPv6) is not a physical device but a piece of software simulating a network interface. The loopback interface is commonly used in test environments.Thejava.net.NetworkInterface
class represents both types of interfaces.
NetworkInterface is useful for a multihomed system, which is a system with multiple NICs. UsingNetworkInterface
, you can specify which NIC to use for a particular network activity.
For example, assume you have a machine with two configured NICs, and you want to send data to a server. You create a socket like this:
To send the data, the system determines which interface will be used. However, if you have a preference or otherwise need to specify which NIC to use, you can query the system for the appropriate interfaces and find an address on the interface you want to use. When you create the socket and bind it to that address, the system will use the associated interface. For example:Socket soc = new java.net.Socket(); soc.connect(new InetSocketAddress(address, port));
You can also useNetworkInterface nif = NetworkInterface.getByName("bge0"); EnumerationnifAddresses = nif.getInetAddresses(); Socket soc = new java.net.Socket(); soc.bind(nifAddresses.nextElement()); soc.connect(new InetSocketAddress(address, port)); NetworkInterface
to identify the local interface on which a multicast group is to be joined. For example:
NetworkInterface can be used with Java APIs in many other ways beyond the two uses described here.NetworkInterface nif = NetworkInterface.getByName("bge0"); MulticastSocket() ms = new MulticastSocket(); ms.joinGroup(new InetSocketAddress(hostname, port) , nif);
Retrieving Network Interfaces
TheNetworkInterface
class has no public constructor. Therefore, you cannot just create a new instance of this class with thenew
operator. Instead, the following static methods are available so that you can retrieve the interface details from the system:getByInetAddress()
,getByName()
, andgetNetworkInterfaces()
. The first two methods are used when you already know the IP address or the name of the particular interface. The third method,getNetworkInterfaces()
returns the complete list of interfaces on the machine.Network interfaces can be hierarchically organized. TheNetworkInterface
class includes two methods,getParent()
andgetSubInterfaces()
, that are pertinent to a network interface hierarchy. ThegetParent()
method returns the parentNetworkInterface
of an interface. If a network interface is a subinterface,getParent()
returns a non-null value. ThegetSubInterfaces()
method returns all the subinterfaces of a network interface.
The following example program lists the name of all the network interfaces and subinterfaces (if any exist) on a machine.
The following is sample output from the example program:import java.io.*; import java.net.*; import java.util.*; import static java.lang.System.out; public class ListNIFs { public static void main(String args[]) throws SocketException { Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); for (NetworkInterface netIf : Collections.list(nets)) { out.printf("Display name: %s\n", netIf.getDisplayName()); out.printf("Name: %s\n", netIf.getName()); displaySubInterfaces(netIf); out.printf("\n"); } } static void displaySubInterfaces(NetworkInterface netIf) throws SocketException { Enumeration<NetworkInterface> subIfs = netIf.getSubInterfaces(); for (NetworkInterface subIf : Collections.list(subIfs)) { out.printf("\tSub Interface Display name: %s\n", subIf.getDisplayName()); out.printf("\tSub Interface Name: %s\n", subIf.getName()); } } }
Display name: bge0 Name: bge0 Sub Interface Display name: bge0:3 Sub Interface Name: bge0:3 Sub Interface Display name: bge0:2 Sub Interface Name: bge0:2 Sub Interface Display name: bge0:1 Sub Interface Name: bge0:1 Display name: lo0 Name: lo0
Listing Network Interface Addresses
One of the most useful pieces of information you can get from a network interface is the list of IP addresses that are assigned to it. You can obtain this information from aNetworkInterface
instance by using one of two methods. The first method,getInetAddresses()
, returns anEnumeration
ofInetAddress
. The other method,getInterfaceAddresses()
, returns a list ofjava.net.InterfaceAddress
instances. This method is used when you need more information about an interface address beyond its IP address. For example, you might need additional information about the subnet mask and broadcast address when the address is an IPv4 address, and a network prefix length in the case of an IPv6 address.The following example program lists all the network interfaces and their addresses on a machine:
The following is sample output from the example program:import java.io.*; import java.net.*; import java.util.*; import static java.lang.System.out; public class ListNets { public static void main(String args[]) throws SocketException { Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); for (NetworkInterface netint : Collections.list(nets)) displayInterfaceInformation(netint); } static void displayInterfaceInformation(NetworkInterface netint) throws SocketException { out.printf("Display name: %s\n", netint.getDisplayName()); out.printf("Name: %s\n", netint.getName()); Enumeration<InetAddress> inetAddresses = netint.getInetAddresses(); for (InetAddress inetAddress : Collections.list(inetAddresses)) { out.printf("InetAddress: %s\n", inetAddress); } out.printf("\n"); } }
Display name: bge0 Name: bge0 InetAddress: /fe80:0:0:0:203:baff:fef2:e99d%2 InetAddress: /121.153.225.59 Display name: lo0 Name: lo0 InetAddress: /0:0:0:0:0:0:0:1%1 InetAddress: /127.0.0.1
Network Interface Parameters
You can access network parameters about a network interface beyond the name and IP addresses assigned to itYou can discover if a network interface is “up” (that is, running) with theisUP()
method. The following methods indicate the network interface type:
The
isLoopback()
indicates if the network interface is a loopback interface.isPointToPoint()
indicates if the interface is a point-to-point interface.isVirtual()
indicates if the interface is a virtual interface.supportsMulticast()
method indicates whether the network interface supports multicasting. ThegetHardwareAddress()
method returns the network interface's physical hardware address, usually called MAC address, when it is available. ThegetMTU()
method returns the Maximum Transmission Unit (MTU), which is the largest packet size.
The following example expands on the example in Listing Network Interface Addresses by adding the additional network parameters described on this page:
The following is sample output from the example program:import java.io.*; import java.net.*; import java.util.*; import static java.lang.System.out; public class ListNetsEx { public static void main(String args[]) throws SocketException { Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); for (NetworkInterface netint : Collections.list(nets)) displayInterfaceInformation(netint); } static void displayInterfaceInformation(NetworkInterface netint) throws SocketException { out.printf("Display name: %s\n", netint.getDisplayName()); out.printf("Name: %s\n", netint.getName()); Enumeration<InetAddress> inetAddresses = netint.getInetAddresses(); for (InetAddress inetAddress : Collections.list(inetAddresses)) { out.printf("InetAddress: %s\n", inetAddress); } out.printf("Up? %s\n", netint.isUp()); out.printf("Loopback? %s\n", netint.isLoopback()); out.printf("PointToPoint? %s\n", netint.isPointToPoint()); out.printf("Supports multicast? %s\n", netint.supportsMulticast()); out.printf("Virtual? %s\n", netint.isVirtual()); out.printf("Hardware address: %s\n", Arrays.toString(netint.getHardwareAddress())); out.printf("MTU: %s\n", netint.getMTU()); out.printf("\n"); } }
Display name: bge0 Name: bge0 InetAddress: /fe80:0:0:0:203:baff:fef2:e99d%2 InetAddress: /129.156.225.59 Up? true Loopback? false PointToPoint? false Supports multicast? false Virtual? false Hardware address: [0, 3, 4, 5, 6, 7] MTU: 1500 Display name: lo0 Name: lo0 InetAddress: /0:0:0:0:0:0:0:1%1 InetAddress: /127.0.0.1 Up? true Loopback? true PointToPoint? false Supports multicast? false Virtual? false Hardware address: null MTU: 8232
Lesson: Working With Cookies
Though you are probably already familiar with cookies, you might not know how to take advantage of them in your Java application. This lesson guides you through the concept of cookies and explains how to set a cookie handler so that your HTTP URL connections will use it.Java SE provides one main class for this functionality,java.net.CookieHandler
, and the following supporting classes and interfaces:java.net.CookieManager
,java.net.CookiePolicy
,java.net.CookieStore
, andjava.net.HttpCookie
.
HTTP State Management With Cookies
This page describes cookies and explains how they are used to provide sessions.CookieHandler Callback Mechanism
This page explains how a cookie handler is called when you access a web site and how to set a cookie handler.Default CookieManager
Java SE provides a default cookie handler implementation that is sufficient in most cases and highly customizable.Custom CookieManager
Here are some examples of how to customize the cookie policy and write your own cookie store.
HTTP State Management With Cookies
The HTTP state management mechanism specifies a way to create a stateful session with HTTP requests and responses.Generally, HTTP request/response pairs are independent of each other. However, the state management mechanism enables clients and servers that can exchange state information to put these pairs in a larger context, which is called a session. The state information used to create and maintain the session is called a cookie.
A cookie is a piece of data that can be stored in a browser's cache. If you visit a web site and then revisit it, the cookie data can be used to identify you as a return visitor. Cookies enable state information, such as an online shopping cart, to be remembered. A cookie can be short term, holding data for a single web session, that is, until you close the browser, or a cookie can be longer term, holding data for a week or a year.
For more information about HTTP state management, see RFC 2965: HTTP State Management Mechanism.
CookieHandler Callback Mechanism
HTTP state management is implemented in Java SE through thejava.net.CookieHandler
class. ACookieHandler
object provides a callback mechanism to provide an HTTP state management policy implementation in the HTTP protocol handler. That is, URLs that use HTTP as the protocol,new URL("http://java.sun.com")
for example, will use the HTTP protocol handler. This protocol handler calls back to theCookieHander
object, if set, to handle the state management.TheCookieHandler
class is an abstract class that has two pairs of related methods. The first pair,getDefault()
andsetDefault(cookieHandler)
, are static methods that enable you to discover the current handler that is installed and to install your own handler.
No default handler is installed, and installing a handler is done on a system-wide basis. For applications running within a secure environment, that is, they have a security manager installed, you must have special permission to get and set the handler. For more information, seejava.net.CookieHandler.getDefault
.
The second pair of related methods,put(uri, responseHeaders)
andget(uri, requestHeaders)
, enable you to set and get all the applicable cookies to and from a cookie cache for the specified URI in the response/request headers, respectively. These methods are abstract, and a concrete implementation of aCookieHandler
must provide the implementation.
Java Web Start and Java Plug-in have a defaultCookieHandler
installed. However, if you are running a stand-alone application and want to enable HTTP state management, you must set a system-wide handler. The next two pages in this lesson show you how to do so.
Default CookieManager
java.net.CookieManager
provides a concrete implementation of aCookieHandler
and for most users is sufficient for handling HTTP state management.CookieManager
separates the storage of cookies from the policy surrounding, accepting, and rejecting them. ACookieManager
is initialized with ajava.net.CookieStore
and ajava.net.CookiePolicy
.CookieStore
manages the storage of the cookies.CookiePolicy
makes policy decisions on cookie acceptance and rejection.The following code shows how to create and set a system-wide CookieManager:
The first line calls the defaultjava.net.CookieManager cm = new java.net.CookieManager(); java.net.CookieHandler.setDefault(cm);CookieManager
constructor to create the instance. The second line calls the staticsetDefault
method ofCookieHander
to set the system-wide handler.The defaultCookieManager
constructor creates a newCookieManager
instance with a default cookie store and accept policy.CookieStore
is the place where any accepted HTTP cookie is stored. If not specified when created, aCookieManager
instance will use an internal in-memory implementation. This implementation is not persistent and only lives for the lifetime of the Java Virtual Machine. Users requiring a persistent store must implement their own store.
The default cookie policy used byCookieManager
isCookiePolicy.ACCEPT_ORIGINAL_SERVER
, which only accepts cookies from the original server. So, theSet-Cookie
response from the server must have a “domain” attribute set, and it must match the domain of the host in the URL. For more information, seejava.net.HttpCookie.domainMatches
. Users requiring a different policy must implement theCookiePolicy
interface and pass it to theCookieManager
constructor or set it to an already constructedCookieManager
instance by using thesetCookiePolicy(cookiePolicy)
method.
When retrieving cookies from the cookie store,CookieManager
also enforces the path-match rule from section 3.3.4 of RFC 2965. So, a cookie must also have its “path” attribute set so that the path-match rule can be applied before the cookie is retrieved from the cookie store.
In summary,CookieManager
provides the framework for handling cookies and provides a good default implementation forCookieStore
.CookieManager
is highly customizable by enabling you to set your ownCookieStore
,CookiePolicy
, or both.
Custom CookieManager
Two aspects of theCookieManager
class can be customized, theCookiePolicy
and theCookieStore
.
CookiePolicy
For convenience,CookiePolicy
defines the following pre-defined policies for accepting cookies:
CookiePolicy.ACCEPT_ORIGINAL_SERVER
only accepts cookies from the original server.CookiePolicy.ACCEPT_ALL
accepts all cookies.CookiePolicy.ACCEPT_NONE
accepts no cookies. You can also define your own cookie policy by implementing theshouldAccept
method ofCookiePolicy
. You can then use thisCookiePolicy
by passing it to the multi-argumentCookieManager
constructor or by calling thesetCookiePolicy(cookiePolicy)
method to change an already existing cookie manager.The following is an example of a cookie policy that rejects cookies from domains that are on a blacklist, before applying theCookiePolicy.ACCEPT_ORIGINAL_SERVER
policy:
When you create aimport java.net.*; public class BlacklistCookiePolicy implements CookiePolicy { String[] blacklist; public BlacklistCookiePolicy(String[] list) { blacklist = list; } public boolean shouldAccept(URI uri, HttpCookie cookie) { String host; try { host = InetAddress.getByName(uri.getHost()).getCanonicalHostName(); } catch (UnknownHostException e) { host = uri.getHost(); } for (int i=0; i<blacklist.length; i++) { if (HttpCookie.domainMatches(blacklist[i], host)) { return false; } } return CookiePolicy.ACCEPT_ORIGINAL_SERVER.shouldAccept(uri, cookie); } }BlacklistCookiePolicy
instance, you pass it an array of strings representing the domains that you do not want to accept cookies from. Then, you set thisBlacklistCookiePolicy
instance as the cookie policy for yourCookieManager
. For example:The sample code will not accept cookies from hosts such as the following:String[] list = new String[] { ".bar.com" }; CookieManager cm = new CookieManager(null, new BlacklistCookiePolicy(list)); CookieHandler.setDefault(cm);However, this sample code will accept cookies from hosts such as the following:foo.bar.com goo.bar.comy.com bar.com x.foo.bar.com
CookieStore
ACookieStore
is an interface that represents a storage area for cookies.CookieManager
adds the cookies to theCookieStore
for every HTTP response and retrieves cookies from theCookieStore
for every HTTP request.You can implement this interface to provide your ownCookieStore
and pass it to theCookieManager
during creation. You cannot set theCookieStore
after theCookieManager
instance has been created. However, you can get a reference to the cookie store by callingCookieManager.getCookieStore()
. Doing so can be useful as it enables you to leverage the default in-memoryCookieStore
implementation that is provided by Java SE and complement its functionality.
For example, you might want to create a persistent cookie store that would save cookies so that they can be used even if the Java Virtual Machine is restarted. Your implementation would work similar to the following:
The following is an incomplete example of this cookie store. This example shows you how to leverage the Java SE default in-memory cookie store and how you might extend its functionality.
- Any cookies that were previously saved are read in.
- During runtime, cookies are stored and retrieved from memory.
- Cookies are written out to persistent storage before exiting.
import java.net.*; import java.util.*; public class PersistentCookieStore implements CookieStore, Runnable { CookieStore store; public PersistentCookieStore() { // get the default in memory cookie store store = new CookieManager().getCookieStore(); // todo: read in cookies from persistant storage // and add them store // add a shutdown hook to write out the in memory cookies Runtime.getRuntime().addShutdownHook(new Thread(this)); } public void run() { // todo: write cookies in store to persistent storage } public void add(URI uri, HttpCookie cookie) { store.add(uri, cookie); } public List<HttpCookie> get(URI uri) { return store.get(uri); } public List<HttpCookie> getCookies() { return store.getCookies(); } public List<URI> getURIs() { return store.getURIs(); } public boolean remove(URI uri, HttpCookie cookie) { return store.remove(uri, cookie); } public boolean removeAll() { return store.removeAll(); } }
0 comments:
Post a Comment