You are on page 1of 160

Java Network Programming

Elliotte Rusty Harold


elharo@metalab.unc.edu
http://metalab.unc.edu/javafaq/slides/

2000 Elliotte Rusty Harold *


We will learn how Java
handles
Internet Addresses
URLs
CGI
Sockets
Server Sockets
UDP

2000 Elliotte Rusty Harold *


I assume you

Understand basic Java syntax and I/O


Have a users view of the Internet
No prior network programming
experience

2000 Elliotte Rusty Harold *


Applet Network Security
Restrictions
Applets may:
send data to the code base
receive data from the code base
Applets may not:
send data to hosts other than the code base
receive data from hosts other than the code
base

2000 Elliotte Rusty Harold *


Some Background

Hosts
Internet Addresses
Ports
Protocols

2000 Elliotte Rusty Harold *


Hosts

Devices connected to the Internet are


called hosts
Most hosts are computers, but hosts also
include routers, printers, fax machines,
soda machines, bat houses, etc.

2000 Elliotte Rusty Harold *


Internet addresses
Every host on the Internet is identified by a
unique, four-byte Internet Protocol (IP)
address.
This is written in dotted quad format like
199.1.32.90 where each byte is an unsigned
integer between 0 and 255.
There are about four billion unique IP
addresses, but they arent very efficiently
allocated
2000 Elliotte Rusty Harold *
Domain Name System (DNS)

Numeric addresses are mapped to names


like www.blackstar.com or
star.blackstar.com by DNS.
Each site runs domain name server
software that translates names to IP
addresses and vice versa
DNS is a distributed system

2000 Elliotte Rusty Harold *


The InetAddress Class
The java.net.InetAddress class
represents an IP address.
It converts numeric addresses to host
names and host names to numeric
addresses.
It is used by other network classes like
Socket and ServerSocket to identify
hosts
2000 Elliotte Rusty Harold *
Creating InetAddresses
There are no public InetAddress()
constructors. Arbitrary addresses may
not be created.
All addresses that are created must be
checked with DNS

2000 Elliotte Rusty Harold *


The getByName() factory
method
public static InetAddress getByName(String
host) throws UnknownHostException

InetAddress utopia, duke;


try {
utopia = InetAddress.getByName("utopia.poly.edu");
duke = InetAddress.getByName("128.238.2.92");
}
catch (UnknownHostException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


Other ways to create
InetAddress objects
public static InetAddress[] getAllByName(String host)
throws UnknownHostException

public static InetAddress getLocalHost() throws


UnknownHostException

2000 Elliotte Rusty Harold *


Getter Methods
public boolean isMulticastAddress()
public String getHostName()
public byte[] getAddress()
public String getHostAddress()

2000 Elliotte Rusty Harold *


Utility Methods
public int hashCode()
public boolean equals(Object o)
public String toString()

2000 Elliotte Rusty Harold *


Ports

In general a host has only one Internet


address
This address is subdivided into 65,536
ports
Ports are logical abstractions that allow
one host to communicate simultaneously
with many other hosts
Many services run on well-known ports.
For example, http tends to run on port 80
2000 Elliotte Rusty Harold *
Protocols
A protocol defines how two hosts talk to
each other.
The daytime protocol, RFC 867, specifies
an ASCII representation for the time
that's legible to humans.
The time protocol, RFC 868, specifies a
binary representation, for the time that's
legible to computers.
There are thousands of protocols,
standard and non-standard
2000 Elliotte Rusty Harold *
IETF RFCs

Requests For Comment


Document how much of the Internet
works
Various status levels from obsolete to
required to informational
TCP/IP, telnet, SMTP, MIME, HTTP,
and more
http://www.faqs.org/rfc/
2000 Elliotte Rusty Harold *
W3C Standards

IETF is based on rough consensus and


running code
W3C tries to run ahead of
implementation
IETF is an informal organization open to
participation by anyone
W3C is a vendor consortium open only to
companies
2000 Elliotte Rusty Harold *
W3C Standards

HTTP
HTML
XML
RDF
MathML
SMIL
P3P
2000 Elliotte Rusty Harold *
URLs

A URL, short for "Uniform Resource


Locator", is a way to unambiguously
identify the location of a resource on the
Internet.

2000 Elliotte Rusty Harold *


Example URLs
http://java.sun.com/
file:///Macintosh%20HD/Java/Docs/JDK%201.1.1%20docs/api/ja
va.net.InetAddress.html#_top_
http://www.macintouch.com:80/newsrecent.shtml
ftp://ftp.info.apple.com/pub/
mailto:elharo@metalab.unc.edu
telnet://utopia.poly.edu
ftp://mp3:mp3@138.247.121.61:21000/c%3a/stuff/mp3/

http://elharo@java.oreilly.com/
http://metalab.unc.edu/nywc/comps.phtml?category=Choral+Wo
rks

2000 Elliotte Rusty Harold *


The Pieces of a URL

the protocol, aka scheme


the authority
user info
user name
password

host name or address


port
the path, a.k.a. file
the ref, a.k.a. section or anchor
the query string
2000 Elliotte Rusty Harold *
The java.net.URL class

A URL object represents a URL.


The URL class contains methods to
create new URLs
parse the different parts of a URL
get an input stream from a URL so you can
read data from a server
get content from the server as a Java object

2000 Elliotte Rusty Harold *


Content and Protocol
Handlers
Content and protocol handlers separate the data
being downloaded from the the protocol used to
download it.
The protocol handler negotiates with the server
and parses any headers. It gives the content
handler only the actual data of the requested
resource.
The content handler translates those bytes into a
Java object like an InputStream or
ImageProducer.
2000 Elliotte Rusty Harold *
Finding Protocol Handlers
When the virtual machine creates a URL
object, it looks for a protocol handler that
understands the protocol part of the URL
such as "http" or "mailto".
If no such handler is found, the
constructor throws a
MalformedURLException.

2000 Elliotte Rusty Harold *


Supported Protocols
The exact protocols that Java supports
vary from implementation to
implementation though http and file are
supported pretty much everywhere.
Sun's JDK 1.1 understands ten:
file appletresource
ftp doc
gopher netdoc
http systemresource
mailto verbatim

2000 Elliotte Rusty Harold *


URL Constructors
There are four (six in 1.2) constructors in the
java.net.URL class.
public URL(String u) throws MalformedURLException
public URL(String protocol, String host, String file)
throws MalformedURLException
public URL(String protocol, String host, int port,
String file) throws MalformedURLException
public URL(URL context, String url) throws
MalformedURLException
public URL(String protocol, String host, int port,
String file, URLStreamHandler handler) throws
MalformedURLException
public URL(URL context, String url, URLStreamHandler
handler) throws MalformedURLException
2000 Elliotte Rusty Harold *
Constructing URL Objects

An absolute URL like


http://www.poly.edu/fall97/grad.html#cs
try {
URL u = new URL(
"http://www.poly.edu/fall97/grad.html#cs");
}
catch (MalformedURLException e) {}

2000 Elliotte Rusty Harold *


Constructing URL Objects in
Pieces
You can also construct the URL by
passing its pieces to the constructor, like
this:
URL u = null;
try {
u = new URL("http", "www.poly.edu",
"/schedule/fall97/bgrad.html#cs");
}
catch (MalformedURLException e) {}

2000 Elliotte Rusty Harold *


Including the Port
URL u = null;
try {
u = new URL("http", "www.poly.edu", 8000,
"/fall97/grad.html#cs");
}
catch (MalformedURLException e) {}

2000 Elliotte Rusty Harold *


Relative URLs

Many HTML files contain relative URLs.


Consider the page
http://metalab.unc.edu/javafaq/index.html
On this page a link to books.html" refers to
http://metalab.unc.edu/javafaq/books.html.

2000 Elliotte Rusty Harold *


Constructing Relative URLs
The fourth constructor creates URLs
relative to a given URL. For example,
try {
URL u1 = new
URL("http://metalab.unc.edu/index.html"
);
URL u2 = new URL(u1, "books.html");
}
catch (MalformedURLException e) {}
This is particularly useful when parsing
HTML.
2000 Elliotte Rusty Harold *
Parsing URLs
The java.net.URL class has five
methods to split a URL into its
component parts. These are:
public String getProtocol()
public String getHost()
public int getPort()
public String getFile()
public String getRef()

2000 Elliotte Rusty Harold *


For example,
try {
URL u = new
URL("http://www.poly.edu/fall97/grad.html#cs ");
System.out.println("The protocol is " +
u.getProtocol());
System.out.println("The host is " + u.getHost());
System.out.println("The port is " + u.getPort());
System.out.println("The file is " + u.getFile());
System.out.println("The anchor is " + u.getRef());
}
catch (MalformedURLException e) { }

2000 Elliotte Rusty Harold *


Parsing URLs

JDK 1.3 adds three more:


public String getAuthority()
public String getUserInfo()
public String getQuery()

2000 Elliotte Rusty Harold *


Missing Pieces
If a port is not explicitly specified in the URL
it's set to -1. This means the default port.
If the ref doesn't exist, it's just null, so watch
out for NullPointerExceptions. Better
yet, test to see that it's non-null before using
it.
If the file is left off completely, e.g.
http://java.sun.com, then it's set to "/".

2000 Elliotte Rusty Harold *


Reading Data from a URL
The openStream() method connects to the
server specified in the URL and returns an
InputStream object fed by the data from that
connection.
public final InputStream openStream() throws
IOException

Any headers that precede the actual data are


stripped off before the stream is opened.
Network connections are less reliable and slower
than files. Buffer with a BufferedReader or a
BufferedInputStream.
2000 Elliotte Rusty Harold *
Webcat
import java.net.*;
import java.io.*;

public class Webcat {


public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
try {
URL u = new URL(args[i]);
InputStream in = u.openStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String theLine;
while ((theLine = br.readLine()) != null) {
System.out.println(theLine);
}
} catch (IOException e) { System.err.println(e);}
}
}
} 2000 Elliotte Rusty Harold *
The Bug in readLine()
What readLine() does:
Sees a carriage return, waits to see if next
character is a line feed before returning
What readLine() should do:
Sees a carriage return, return, throw away
next character if it's a linefeed

2000 Elliotte Rusty Harold *


Webcat
import java.net.*;
import java.io.*;

public class Webcat {


public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
try {
URL u = new URL(args[i]);
InputStream in = u.openStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
int c;
while ((c = br.read()) != -1) {
System.out.write(c);
}
} catch (IOException e) { System.err.println(e);}
}
}
} 2000 Elliotte Rusty Harold *
CGI

Common Gateway Interface


A lot is written about writing server side
CGI. Im going to show you client side
CGI.
Well need to explore HTTP a little
deeper to do this

2000 Elliotte Rusty Harold *


Normal web surfing uses
these two steps:
The browser requests a page
The server sends the page
Data flows primarily from the server to
the client.

2000 Elliotte Rusty Harold *


Forms

There are times when the server needs to


get data from the client rather than the
other way around. The common way to
do this is with a form like this one:

2000 Elliotte Rusty Harold *


CGI
The user types data into a form and hits the
submit button.
The browser sends the data to the server
using the Common Gateway Interface, CGI.
CGI uses the HTTP protocol to transmit the
data, either as part of the query string or as
separate data following the MIME header.

2000 Elliotte Rusty Harold *


GET and POST

When the data is sent as a query string


included with the file request, this is
called CGI GET.
When the data is sent as data attached to
the request following the MIME header,
this is called CGI POST

2000 Elliotte Rusty Harold *


HTTP
Web browsers communicate with web servers
through a standard protocol known as HTTP,
an acronym for HyperText Transfer Protocol.
This protocol defines
how a browser requests a file from a web server
how a browser sends additional data along with
the request (e.g. the data formats it can accept),
how the server sends data back to the client
response codes

2000 Elliotte Rusty Harold *


A Typical HTTP Connection
Client opens a socket to port 80 on the server.
Client sends a GET request including the name
and path of the file it wants and the version of
the HTTP protocol it supports.
The client sends a MIME header.
The client sends a blank line.
The server sends a MIME header
The server sends the data in the file.
The server closes the connection.

2000 Elliotte Rusty Harold *


What the client sends to the
server

GET /javafaq/images/cup.gif HTTP/1.0


Connection: Keep-Alive
User-Agent: Mozilla/3.01 (Macintosh; I; PPC)
Host: www.oreilly.com:80
Accept: image/gif, image/x-xbitmap, image/jpeg, */*

2000 Elliotte Rusty Harold *


MIME

MIME is an acronym for "Multipurpose


Internet Mail Extensions".
an Internet standard defined in RFCs
2045 through 2049
originally intended for use with email
messages, but has been been adopted for
use in HTTP.

2000 Elliotte Rusty Harold *


Browser Request MIME
Header
When the browser sends a request to a
web server, it also sends a MIME header.
MIME headers contain name-value pairs,
essentially a name followed by a colon
and a space, followed by a value.
Connection: Keep-Alive
User-Agent: Mozilla/3.01 (Macintosh; I; PPC)
Host: www.digitalthink.com:80
Accept: image/gif, image/x-xbitmap,
image/jpeg, image/pjpeg, */*

2000 Elliotte Rusty Harold *


Server Response MIME
Header
When a web server responds to a web
browser it sends a response message and
a MIME header along with the response
that looks something like this:
HTTP/1.0 200 OK
Server: Netscape-Enterprise/2.01
Date: Sat, 02 Aug 1997 07:52:46 GMT
Accept-ranges: bytes
Last-modified: Tue, 29 Jul 1997 15:06:46 GMT
Content-length: 2810
Content-type: text/html

2000 Elliotte Rusty Harold *


Query Strings

CGI GET data is sent in URL encoded


query strings
a query string is a set of name=value
pairs separated by ampersands
Author=Sadie, Julie&Title=Women Composers

separated from rest of URL by a question


mark

2000 Elliotte Rusty Harold *


URL Encoding
Alphanumeric ASCII characters (a-z, A-Z,
and 0-9) and the $-_.!*'(), punctuation
symbols are left unchanged.
The space character is converted into a plus
sign (+).
Other characters (e.g. &, =, ^, #, %, ^, {,
and so on) are translated into a percent sign
followed by the two hexadecimal digits
corresponding to their numeric value.
2000 Elliotte Rusty Harold *
For example,

The comma is ASCII character 44


(decimal) or 2C (hex). Therefore if the
comma appears as part of a URL it is
encoded as %2C.
The query string "Author=Sadie,
Julie&Title=Women Composers" is
encoded as:
Author=Sadie%2C+Julie&Title=Women+Composers

2000 Elliotte Rusty Harold *


The URLEncoder class
The java.net.URLEncoder class
contains a single static method which
encodes strings in x-www-form-url-
encoded format
URLEncoder.encode(String s)

2000 Elliotte Rusty Harold *


For example,
String qs = "Author=Sadie, Julie&Title=Women Composers";
String eqs = URLEncoder.encode(qs);
System.out.println(eqs);

This prints:
Author%3dSadie%2c+Julie%26Title%3dWomen+Composers

2000 Elliotte Rusty Harold *


String eqs = "Author=" +
URLEncoder.encode("Sadie, Julie");
eqs += "&";
eqs += "Title=";
eqs += URLEncoder.encode("Women Composers");

This prints the properly encoded query


string:
Author=Sadie%2c+Julie&Title=Women+Composers

2000 Elliotte Rusty Harold *


The URLDecoder class

In Java 1.2 the


java.net.URLDecoder class contains
a single static method which decodes
strings in x-www-form-url-encoded
format
URLEncoder.decode(String s)

2000 Elliotte Rusty Harold *


GET URLs
String eqs =
"Author=" + URLEncoder.encode("Sadie, Julie");
eqs += "&";
eqs += "Title=";
eqs += URLEncoder.encode("Women Composers");
try {
URL u = new
URL("http://www.superbooks.com/search.cgi?" + eqs);
InputStream in = u.openStream();
//...
}
catch (IOException e) { //...

2000 Elliotte Rusty Harold *


URLConnections
The java.net.URLConnection class
is an abstract class that handles
communication with different kinds of
servers like ftp servers and web servers.
Protocol specific subclasses of
URLConnection handle different kinds
of servers.
By default, connections to HTTP URLs
use the GET method.
2000 Elliotte Rusty Harold *
URLConnections vs. URLs

Can send output as well as read input


Can post data to CGIs
Can read headers from a connection

2000 Elliotte Rusty Harold *


URLConnection five steps:
1. The URL is constructed.
2. The URLs openConnection() method
creates the URLConnection object.
3. The parameters for the connection and the
request properties that the client sends to the
server are set up.
4. The connect() method makes the connection
to the server. (optional)
5. The response header information is read using
getHeaderField().
2000 Elliotte Rusty Harold *
I/O Across a URLConnection

Data may be read from the connection in


one of two ways
raw by using the input stream returned by
getInputStream()
through a content handler with
getContent().
Data can be sent to the server using the
output stream provided by
getOutputStream().

2000 Elliotte Rusty Harold *


For example,
try {
URL u = new URL("http://www.wwwac.org/");
URLConnection uc = u.openConnection();
uc.connect();
InputStream in = uc.getInputStream();
// read the data...
}
catch (IOException e) { //...

2000 Elliotte Rusty Harold *


Reading Header Data
The getHeaderField(String name)
method returns the string value of a named
header field.
Names are case-insensitive.
If the requested field is not present, null is
returned.
String lm = uc.getHeaderField("Last-modified");

2000 Elliotte Rusty Harold *


getHeaderFieldKey()

The keys of the header fields are returned by


the getHeaderFieldKey(int n)
method.
The first field is 1.
If a numbered key is not found, null is
returned.
You can use this in combination with
getHeaderField() to loop through the
complete header
2000 Elliotte Rusty Harold *
For example
String key = null;
for (int i=1; (key =
uc.getHeaderFieldKey(i))!=null); i++) {
System.out.println(key + ": " +
uc.getHeaderField(key));
}

2000 Elliotte Rusty Harold *


getHeaderFieldInt() and
getHeaderFieldDate()
Utility methods that read a named header and
convert its value into an int and a long
respectively.
public int getHeaderFieldInt(String name, int default)
public long getHeaderFieldDate(String name, long
default)

2000 Elliotte Rusty Harold *


The long returned by
getHeaderFieldDate() can be converted
into a Date object using a Date() constructor
like this:
long lm = uc.getHeaderFieldDate("Last-modified", 0);
Date lastModified = new Date(lm);

2000 Elliotte Rusty Harold *


Six Convenience Methods

These return the values of six


particularly common header fields:
public int getContentLength()
public String getContentType()
public String getContentEncoding()
public long getExpiration()
public long getDate()
public long getLastModified()

2000 Elliotte Rusty Harold *


try {
URL u = new URL("http://www.sdexpo.com/");
URLConnection uc = u.openConnection();
uc.connect();
String key=null;
for (int n = 1;
(key=uc.getHeaderFieldKey(n)) != null;
n++) {
System.out.println(key + ": " +
uc.getHeaderField(key));
}
}
catch (IOException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


Writing data to a
URLConnection

Similar to reading data from a URLConnection.


First inform the URLConnection that you plan to
use it for output
Before getting the connection's input stream, get
the connection's output stream and write to it.
Commonly used to talk to CGIs that use the
POST method

2000 Elliotte Rusty Harold *


Eight Steps:
1.Construct the URL.
2.Call the URLs openConnection()
method to create the URLConnection object.
3.Pass true to the URLConnections
setDoOutput() method
4.Create the data you want to send, preferably
as a byte array.

2000 Elliotte Rusty Harold *


5.Call getOutputStream() to get an
output stream object.
6.Write the byte array calculated in step 5
onto the stream.
7.Close the output stream.
8.Call getInputStream() to get an
input stream object. Read from it as
usual.
2000 Elliotte Rusty Harold *
POST CGIs

A typical POST request to a CGI looks like


this:
POST /cgi-bin/booksearch.pl HTTP/1.0
Referer: http://www.macfaq.com/sampleform.html
User-Agent: Mozilla/3.01 (Macintosh; I; PPC)
Content-length: 60
Content-type: text/x-www-form-urlencoded
Host: utopia.poly.edu:56435

username=Sadie%2C+Julie&realname=Women+Composers

2000 Elliotte Rusty Harold *


A POST request includes

the POST line


a MIME header which must include
content type
content length
a blank line that signals the end of the
MIME header
the actual data of the form, encoded in x-
www-form-urlencoded format.
2000 Elliotte Rusty Harold *
A URLConnection for an http URL will
set up the request line and the MIME
header for you as long as you set its
doOutput field to true by invoking
setDoOutput(true).
If you also want to read from the
connection, you should set doInput to
true with setDoInput(true) too.
2000 Elliotte Rusty Harold *
For example,
URLConnection uc = u.openConnection();
uc.setDoOutput(true);
uc.setDoInput(true);

2000 Elliotte Rusty Harold *


The request line and MIME header are
sent as soon as the URLConnection
connects. Then getOutputStream()
returns an output stream on which you
can write the x-www-form-urlencoded
name-value pairs.

2000 Elliotte Rusty Harold *


HttpURLConnection
java.net.HttpURLConnection is
an abstract subclass of URLConnection
that provides some additional methods
specific to the HTTP protocol.
URL connection objects that are
returned by an http URL will be
instances of
java.net.HttpURLConnection.
2000 Elliotte Rusty Harold *
Recall
a typical HTTP response from a web
server begins like this:
HTTP/1.0 200 OK
Server: Netscape-Enterprise/2.01
Date: Sat, 02 Aug 1997 07:52:46 GMT
Accept-ranges: bytes
Last-modified: Tue, 29 Jul 1997 15:06:46 GMT
Content-length: 2810
Content-type: text/html

2000 Elliotte Rusty Harold *


Response Codes
The getHeaderField() and
getHeaderFieldKey() don't return the
HTTP response code
After you've connected, you can retrieve the
numeric response code--200 in the above
example--with the getResponseCode()
method and the message associated with it--
OK in the above example--with the
getResponseMessage() method.

2000 Elliotte Rusty Harold *


HTTP Protocols
Java 1.0 only supports GET and POST
requests to HTTP servers
Java 1.1/1.2 supports GET, POST, HEAD,
OPTIONS, PUT, DELETE, and TRACE.
The protocol is chosen with the
setRequestMethod(String method)
method.
A java.net.ProtocolException, a
subclass of IOException, is thrown if an
unknown protocol is specified.
2000 Elliotte Rusty Harold *
getRequestMethod()
The getRequestMethod() method
returns the string form of the request
method currently set for the
URLConnection. GET is the default
method.

2000 Elliotte Rusty Harold *


disconnect()
The disconnect() method of the
HttpURLConnection class closes the
connection to the web server.
Needed for HTTP/1.1 Keep-alive

2000 Elliotte Rusty Harold *


For example,
try {
URL u = new URL(
"http://www.metalab.unc.edu/javafaq/books.
html" );
HttpURLConnection huc =
(HttpURLConnection) u.openConnection();
huc.setRequestMethod("PUT");
huc.connect();
OutputStream os = huc.getOutputStream();
int code = huc.getResponseCode();
if (code >= 200 && < 300) {
// put the data...
}
huc.disconnect();
}
catch (IOException e) { //...
2000 Elliotte Rusty Harold *
usingProxy
The boolean usingProxy() method
returns true if web connections are being
funneled through a proxy server, false if
they're not.

2000 Elliotte Rusty Harold *


Redirect Instructions
Most web servers can be configured to
automatically redirect browsers to the
new location of a page that's moved.
To redirect browsers, a server sends a
300 level response and a Location header
that specifies the new location of the
requested page.

2000 Elliotte Rusty Harold *


GET /~elharo/macfaq/index.html HTTP/1.0

HTTP/1.1 302 Moved Temporarily


Date: Mon, 04 Aug 1997 14:21:27 GMT
Server: Apache/1.2b7
Location: http://www.macfaq.com/macfaq/index.html
Connection: close
Content-type: text/html

<HTML><HEAD>
<TITLE>302 Moved Temporarily</TITLE>
</HEAD><BODY>
<H1>Moved Temporarily</H1>
The document has moved <A
HREF="http://www.macfaq.com/macfaq/index.html">he
re</A>.<P>
</BODY></HTML>

2000 Elliotte Rusty Harold *


HTML is returned for browsers that
don't understand redirects, but most
modern browsers jump straight to the
page specified in the Location header
instead.
Because redirects can change the site
which a user is connecting without their
knowledge so redirects are not arbitrarily
followed by URLConnections.

2000 Elliotte Rusty Harold *


Following Redirects
HttpURLConnection.setFollowRedirects
(true) method says that connections will follow
redirect instructions from the web server.
Untrusted applets are not allowed to set this.
HttpURLConnection.getFollowRedirects
() returns true if redirect requests are honored,
false if they're not.

2000 Elliotte Rusty Harold *


Datagrams
Before data is sent across the Internet
from one host to another using TCP/IP, it
is split into packets of varying but finite
size called datagrams.
Datagrams range in size from a few dozen
bytes to about 60,000 bytes.
Packets larger than this, and often smaller
than this, must be split into smaller pieces
before they can be transmitted.
2000 Elliotte Rusty Harold *
Packets Allow Error
Correction
If one packet is lost, it can be
retransmitted without requiring
redelivery of all other packets.
If packets arrive out of order they can be
reordered at the receiving end of the
connection.

2000 Elliotte Rusty Harold *


Abstraction
Datagrams are mostly hidden from the
Java programmer.
The host's native networking software
transparently splits data into packets on
the sending end of a connection, and then
reassembles packets on the receiving end.
Instead, the Java programmer is
presented with a higher level abstraction
called a socket.
2000 Elliotte Rusty Harold *
Sockets
A socket is a reliable connection for the
transmission of data between two hosts.
Sockets isolate programmers from the
details of packet encodings, lost and
retransmitted packets, and packets that
arrive out of order.
There are limits. Sockets are more likely to
throw IOExceptions than files, for example.

2000 Elliotte Rusty Harold *


Socket Operations

There are four fundamental operations a


socket performs. These are:
1. Connect to a remote machine
2. Send data
3. Receive data
4. Close the connection
A socket may not be connected to more than
one host at a time.
A socket may not reconnect after it's closed.
2000 Elliotte Rusty Harold *
The java.net.Socket class
The java.net.Socket class allows you to
create socket objects that perform all four
fundamental socket operations.
You can connect to remote machines; you can
send data; you can receive data; you can close
the connection.
Each Socket object is associated with exactly
one remote host. To connect to a different host,
you must create a new Socket object.
2000 Elliotte Rusty Harold *
Constructing a Socket
Connection is accomplished through the
constructors.
public Socket(String host, int port) throws
UnknownHostException, IOException
public Socket(InetAddress address, int port)
throws IOException
public Socket(String host, int port, InetAddress
localAddr, int localPort) throws IOException
public Socket(InetAddress address, int port,
InetAddress localAddr, int localPort) throws
IOException

2000 Elliotte Rusty Harold *


Opening Sockets
The Socket() constructors do not just
create a Socket object. They also attempt
to connect the underlying socket to the
remote server.
All the constructors throw an
IOException if the connection can't be
made for any reason.

2000 Elliotte Rusty Harold *


You must at least specify the remote host and
port to connect to.
The host may be specified as either a string like
"utopia.poly.edu" or as an InetAddress
object.
The port should be an int between 1 and 65535.
Socket webMetalab = new Socket("metalab.unc.edu",
80);

2000 Elliotte Rusty Harold *


You cannot just connect to any port on
any host. The remote host must actually be
listening for connections on that port.
You can use the constructors to determine
which ports on a host are listening for
connections.

2000 Elliotte Rusty Harold *


public static void scan(InetAddress remote) {
String hostname = remote.getHostName();
for (int port = 0; port < 65536; port++) {
try {
Socket s = new Socket(remote, port);
System.out.println("There is a server on port "
+ port + " of " + hostname);
s.close();
}
catch (IOException e) {
// The remote host is not listening on this port
}
}
}

2000 Elliotte Rusty Harold *


Picking an IP address

The last two constructors also specify the


host and port you're connecting from.
On a system with multiple IP addresses,
like many web servers, this allows you to
pick your network interface and IP
address.

2000 Elliotte Rusty Harold *


Choosing a Local Port
You can also specify a local port number,
Setting the port to 0 tells the system to randomly
choose an available port.
If you need to know the port you're connecting
from, you can always get it with
getLocalPort().
Socket webMetalab = new Socket("metalab.unc.edu",
80, "calzone.oit.unc.edu", 0);

2000 Elliotte Rusty Harold *


Sending and Receiving Data
Data is sent and received with output and
input streams.
There are methods to get an input stream for
a socket and an output stream for the socket.
public InputStream getInputStream() throws
IOException
public OutputStream getOutputStream() throws
IOException

There's also a method to close a socket.


public synchronized void close() throws
IOException
2000 Elliotte Rusty Harold *
Reading Input from a Socket
The getInputStream() method returns an
InputStream which reads data from the
socket.
You can use all the normal methods of the
InputStream class to read this data.
Most of the time you'll chain the input stream
to some other input stream or reader object to
more easily handle the data.
2000 Elliotte Rusty Harold *
For example
The following code fragment connects to the
daytime server on port 13 of metalab.unc.edu,
and displays the data it sends.
try {
Socket s = new Socket("metalab.unc.edu", 13);
InputStream in = s.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String theTime = br.readLine();
System.out.println(theTime);
}
catch (IOException e) {
return (new Date()).toString();
}
2000 Elliotte Rusty Harold *
Writing Output to a Socket
The getOutputStream() method
returns an output stream which writes
data to the socket.
Most of the time you'll chain the raw
output stream to some other output
stream or writer class to more easily
handle the data.

2000 Elliotte Rusty Harold *


Discard
byte[] b = new byte[128];
try {
Socket s = new Socket("metalab.unc.edu", 9);
OutputStream theOutput = s.getOutputStream();
while (true) {
int n = theInput.available();
if (n > b.length) n = b.length;
int m = theInput.read(b, 0, n);
if (m == -1) break;
theOutput.write(b, 0, n);
}
s.close();
}
catch (IOException e) {}

2000 Elliotte Rusty Harold *


Reading and Writing to a
Socket
It's unusual to only read from a socket.
It's even more unusual to only write to a
socket.
Most protocols require the client to both
read and write.

2000 Elliotte Rusty Harold *


Some protocols require the reads and the
writes to be interlaced. That is:
write
read
write
read
write
read

2000 Elliotte Rusty Harold *


Other protocols, such as HTTP 1.0, have
multiple writes, followed by multiple
reads, like this:
write
write
write
read
read
read
read

2000 Elliotte Rusty Harold *


Other protocols don't care and allow client
requests and server responses to be freely
intermixed.
Java places no restrictions on reading and
writing to sockets.
One thread can read from a socket while
another thread writes to the socket at the
same time.
2000 Elliotte Rusty Harold *
try {
URL u = new URL(args[i]);
if (u.getPort() != -1) port = u.getPort();
if (!(u.getProtocol().equalsIgnoreCase("http"))) {
System.err.println("I only understand http.");
}
Socket s = new Socket(u.getHost(), u.getPort());
OutputStream theOutput = s.getOutputStream();
PrintWriter pw = new PrintWriter(theOutput, false);
pw.print("GET " + u.getFile() + " HTTP/1.0\r\n");
pw.print("Accept: text/plain, text/html, text/*\r\n");
pw.print("\r\n");
pw.flush();
InputStream in = s.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
int c;
while ((c = br.read()) != -1) {
System.out.write(c);
}
}
2000 Elliotte Rusty Harold
catch (MalformedURLException* e) {
Socket Options
Several methods set various socket options.
Most of the time the defaults are fine.
public void setTcpNoDelay(boolean on) throws
SocketException
public boolean getTcpNoDelay() throws SocketException
public void setSoLinger(boolean on, int val) throws
SocketException
public int getSoLinger() throws SocketException
public synchronized void setSoTimeout(int timeout)
throws SocketException
public synchronized int getSoTimeout() throws
SocketException

2000 Elliotte Rusty Harold *


These methods to return information
about the socket:
public InetAddress getInetAddress()
public InetAddress getLocalAddress()
public int getPort()
public int getLocalPort()

Finally there's the usual toString()


method:
public String toString()

2000 Elliotte Rusty Harold *


Servers
There are two ends to each connection: the
client, that is the host that initiates the
connection, and the server, that is the host
that responds to the connection.
Clients and servers are connected by sockets.
A server, rather than connecting to a remote
host, a program waits for other hosts to
connect to it.

2000 Elliotte Rusty Harold *


Server Sockets

A server socket binds to a particular port on


the local machine.
Once it has successfully bound to a port, it
listens for incoming connection attempts.
When a server detects a connection attempt, it
accepts the connection. This creates a socket
between the client and the server over which
the client and the server communicate.
2000 Elliotte Rusty Harold *
Multiple Clients
Multiple clients can connect to the same port on
the server at the same time.
Incoming data is distinguished by the port to
which it is addressed and the client host and port
from which it came.
The server can tell for which service (like http or
ftp) the data is intended by inspecting the port.
It can tell which open socket on that service the
data is intended for by looking at the client
address and port stored with the data.
2000 Elliotte Rusty Harold *
Queueing

Incoming connections are stored in a


queue until the server can accept them.
On most systems the default queue length
is between 5 and 50.
Once the queue fills up further incoming
connections are refused until space in the
queue opens up.

2000 Elliotte Rusty Harold *


The java.net.ServerSocket
Class
The java.net.ServerSocket class
represents a server socket.
A ServerSocket object is constructed on a
particular local port. Then it calls accept()
to listen for incoming connections.
accept() blocks until a connection is
detected. Then accept() returns a
java.net.Socket object that performs the
actual communication with the client.
2000 Elliotte Rusty Harold *
Constructors

There are three constructors that let you


specify the port to bind to, the queue
length for incoming connections, and the
IP address to bind to:
public ServerSocket(int port) throws IOException
public ServerSocket(int port, int backlog)
throws IOException
public ServerSocket(int port, int backlog,
InetAddress networkInterface) throws
IOException

2000 Elliotte Rusty Harold *


Constructing Server Sockets

Normally you only specify the port you


want to listen on, like this:
try {
ServerSocket ss = new ServerSocket(80);
}
catch (IOException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


When a ServerSocket object is created, it
attempts to bind to the port on the local host
given by the port argument.
If another server socket is already listening to
the port, then a
java.net.BindException, a subclass of
IOException, is thrown.
No more than one process or thread can listen
to a particular port at a time. This includes
non-Java processes or threads.
For example, if there's already an HTTP
server running on port 80, you won't be able to
2000 Elliotte Rusty Harold *
On Unix systems (but not Windows or the
Mac) your program must be running as root to
bind to a port between 1 and 1023.
0 is a special port number. It tells Java to pick
an available port.
The getLocalPort() method tells you what
port the server socket is listening on. This is
useful if the client and the server have already
established a separate channel of
communication over which the chosen port
number can be communicated.
FTP
2000 Elliotte Rusty Harold *
Expanding the Queue

If you think you aren't going to be


processing connections very quickly you may
wish to expand the queue when you
construct the server socket. For example,
try {
ServerSocket httpd = new ServerSocket(80,
50);
}
catch (IOException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


Choosing an IP address

Many hosts have more than one IP


address.
By default, a server socket binds to all
available IP addresses on a given port.
You can modify that behavior with this
constructor:
public ServerSocket(int port, int backlog,
InetAddress bindAddr)throws IOException

2000 Elliotte Rusty Harold *


Example
try {
InetAddress ia =
InetAddress.getByName("199.1.32.90");
ServerSocket ss = new ServerSocket(80, 50, ia);
}
catch (IOException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


On a server with multiple IP addresses,
the getInetAddress() method tells
you which one this server socket is
listening to.
public InetAddress getInetAddress()

The getLocalPort() method tells you


which port you're listening to.
public int getLocalPort()

2000 Elliotte Rusty Harold *


The accept() and close() methods
provide the basic functionality of a server
socket.
public Socket accept() throws IOException
public void close() throws IOException

A server socket cant be reopened after


its closed

2000 Elliotte Rusty Harold *


Reading Data with a
ServerSocket
ServerSocket objects use their accept()
method to connect to a client.
public Socket accept() throws IOException

There are no getInputStream() or


getOutputStream() methods for
ServerSocket.
accept() returns a Socket object, and its
getInputStream() and
getOutputStream() methods provide
streams.
2000 Elliotte Rusty Harold *
Example
try {
ServerSocket ss = new ServerSocket(2345);
Socket s = ss.accept();
PrintWriter pw = new
PrintWriter(s.getOutputStream());
pw.println("Hello There!");
pw.println("Goodbye now.");
s.close();
}
catch (IOException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


Better Example
try {
ServerSocket ss = new ServerSocket(2345);
Socket s = ss.accept();
PrintWriter pw = new
PrintWriter(s.getOutputStream());
pw.print("Hello There!\r\n");
pw.print("Goodbye now.\r\n");
s.close();
}
catch (IOException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


Writing Data to a Client
try {
ServerSocket ss = new ServerSocket(port);
while (true) {
try {
Socket s = ss.accept();
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.print("Hello " + s.getInetAddress() + " on port "
+ s.getPort() + "\r\n");
pw.print("This is " + s.getLocalAddress() + " on port
"
+ s.getLocalPort() + "\r\n");
pw.flush();
s.close();
}
catch (IOException e) {}
}
}
catch
(IOException
2000 Elliotte Rusty Harold e) { System.err.println(e);
* }
Interacting with a Client

More commonly, a server needs to both


read a client request and write a response.

2000 Elliotte Rusty Harold *


Threading

No more than one server socket can listen


to a particular port at one time.
Since a server may need to handle many
connections at once, server programs tend
to be heavily multi-threaded.
Generally the server socket passes off the
actual processing of connections to a
separate thread.
2000 Elliotte Rusty Harold *
Adding Threading to a Server

It's better to make your server multi-


threaded.
There should be a loop which continually
accepts new connections.
Rather than handling the connection
directly the socket should be passed to a
Thread object that handles the
connection.
2000 Elliotte Rusty Harold *
Adding a Thread Pool to a
Server
Multi-threading is a good thing but it's still not a
perfect solution.
Look at this accept loop:
while (true) {
try {
Socket s = ss.accept();
ThreadedEchoServer tes = new ThreadedEchoServer(s)
tes.start();
}
catch (IOException e) {}

2000 Elliotte Rusty Harold *


Every pass through this loop, a new thread
gets created. Every time a connection is
finished the thread is disposed of.
Spawning a new thread for each
connection takes a non-trivial amount of
time, especially on a heavily loaded server.
Too many simultaneous threads overload
a VM.
2000 Elliotte Rusty Harold *
Thread Pools

Create a pool of threads when the server


launches, store incoming connections in a
queue, and have the threads in the pool
progressively remove connections from the
queue and process them.
The main change you need to make to
implement this is to call accept() in the
run() method rather than in the main()
method.
2000 Elliotte Rusty Harold *
Setting Server Socket
Options
There are three methods to set and get
various options. The defaults are generally
fine.
public synchronized void setSoTimeout(int
timeout) throws SocketException
public synchronized int getSoTimeout() throws
IOException
public static synchronized void
setSocketFactory(SocketImplFactory fac)
throws IOException

2000 Elliotte Rusty Harold *


Utility Methods
Finally, there's the usual toString()
method:
public String toString()

2000 Elliotte Rusty Harold *


UDP

Unreliable Datagram Protocol


Packet Oriented, not stream oriented like
TCP/IP
Much faster but no error correction
NFS, TFTP, and FSP use UDP/IP
Must fit data into packets of about 8K or
less

2000 Elliotte Rusty Harold *


The UDP Classes

Java's support for UDP is contained in


two classes:
java.net.DatagramSocket
java.net.DatagramPacket
A datagram socket is used to send and
receive datagram packets.

2000 Elliotte Rusty Harold *


java.net.DatagramPacket

a wrapper for an array of bytes from


which data will be sent or into which data
will be received.
also contains the address and port to
which the packet will be sent.

2000 Elliotte Rusty Harold *


java.net.DatagramSocket
A DatagramSocket object is a local
connection to a port that does the sending and
receiving.
There is no distinction between a UDP socket
and a UDP server socket.
Also unlike TCP sockets, a DatagramSocket
can send to multiple, different addresses.
The address to which data goes is stored in the
packet, not in the socket.
2000 Elliotte Rusty Harold *
UDP ports

Separate from TCP ports.


Each computer has 65,536 UDP ports as
well as its 65,536 TCP ports.
A server socket can be bound to TCP port
20 at the same time as a datagram socket
is bound to UDP port 20.

2000 Elliotte Rusty Harold *


Two DatagramPacket
Constructors
public DatagramPacket(byte[] data,
int length)
public DatagramPacket(byte[] data,
int length, InetAddress remote,
int port)
First is for receiving, second is for sending

2000 Elliotte Rusty Harold *


For example,
String s = "My first UDP Packet";
byte[] b = s.getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length);

2000 Elliotte Rusty Harold *


With a destination:
try {
InetAddress metalab =
InetAddress.getByName("metalab.unc.edu");
int chargen = 19;
String s = "My second UDP Packet";
byte[] b = s.getBytes();
DatagramPacket dp = new DatagramPacket(b,
b.length, metalab, chargen);
}
catch (UnknownHostException e) {
System.err.println(e);
}

2000 Elliotte Rusty Harold *


DatagramPackets are not
immutable.
public synchronized void
setAddress(InetAddress remote)
public synchronized void setPort(int port)
public synchronized void setData(byte[] data)
public synchronized void setLength(int
length)
public synchronized InetAddress getAddress()
public synchronized int getPort()
public synchronized byte[] getData()
public synchronized int getLength()

These methods are primarily useful when


you're receiving datagrams.
2000 Elliotte Rusty Harold *
java.net.DatagramSocket
public DatagramSocket() throws
SocketException
public DatagramSocket(int port) throws
SocketException
public DatagramSocket(int port, InetAddress
laddr) throws SocketException

The first is for client datagram sockets;


that is sockets that send datagrams before
receiving any.
The second two are for server datagram
sockets since they specify the port and
optionally the IP address of the socket
2000 Elliotte Rusty Harold *
Sending UDP Datagrams

To send data to a particular server


Convert the data into byte array.
Pass this byte array, the length of the data in
the array (most of the time this will be the
length of the array) and the InetAddress
and port to which you wish to send it into the
DatagramPacket() constructor.
Next create a DatagramSocket and pass the
packet to its send() method
2000 Elliotte Rusty Harold *
For example,
InetAddress metalab =
InetAddress.getByName("metalab.unc.edu");
int chargen = 19;
String s = "My second UDP Packet";
byte[] b = s.getBytes();
DatagramPacket dp = new DatagramPacket(b,
b.length, ia, chargen);
DatagramSocket sender = new DatagramSocket();
sender.send(dp);

2000 Elliotte Rusty Harold *


Receiving UDP Datagrams
Construct a DatagramSocket object on
the port on which you want to listen.
Pass an empty DatagramPacket object to
the DatagramSocket's receive()
method.
public synchronized void receive(DatagramPacket
dp) throws IOException

The calling thread blocks until a datagram is


received.
2000 Elliotte Rusty Harold *
dp is filled with the data from that
datagram.
Use getPort() and and getAddress()
to tell where the packet came from,
getData() to retrieve the data, and
getLength() to see how many bytes were
in the data.
If the received packet was too long for the
buffer, it's truncated to the length of the
buffer.
2000 Elliotte Rusty Harold *
For example,
try {
byte buffer = new byte[65536];
DatagramPacket incoming = new
DatagramPacket(buffer, buffer.length);
DatagramSocket ds = new
DatagramSocket(2134);
ds.receive(incoming);
byte[] data = incoming.getData();
String s = new String(data, 0,
data.getLength());
System.out.println("Port " +
incoming.getPort() + " on " +
incoming.getAddress() + " sent this
message:");
System.out.println(s);
}
catch (IOException e) {
System.err.println(e);
2000 Elliotte Rusty Harold *
}
Receiving Multiple Packets

Watch out for strictly decreasing packet


sizes
DatagramPacket incoming = new
DatagramPacket(new byte[8192], 8192);
DatagramSocket ds = new
DatagramSocket(2134);
while (true) {
try {
incoming.setLength(8192);
ds.receive(incoming);
byte[] data = incoming.getData();
String s = new String(data, 0,
data.getLength());
2000 Elliotte Rusty Harold
System.out.println("Port
*
" +
To Learn More
Java Network Programming
OReilly & Associates, 1997
ISBN 1-56592-227-1
Java I/O
OReilly & Associates, 1999
ISBN 1-56592-485-1
Web Client Programming with Java
http://www.digitalthink.com/catalog/cs/cs
308/index.html

2000 Elliotte Rusty Harold *


Questions?

2000 Elliotte Rusty Harold *

You might also like