Sie sind auf Seite 1von 120

Preface

For years, college courses in comput er net worki ng were t aught with little or no hands on expe-
rience. For various reasons, including some good ones, i nst ruct ors approached the principles
of comput er net worki ng primarily t hrough equations, analyses, and abst ract descriptions of
protocol stacks. Textbooks mi ght have included code, but it would have been unconnect ed to
anything st udent s could get their hands on. We believe, however, that st udent s learn bet t er
when they can see (and t hen build) concrete exampl es of the principles at work. And, for-
tunately, things have changed. The Internet has become a part of everyday life, and access
to its services is readily available to most st udent s (and their programs). Moreover, copious
exampl esugood and bad- - of nontrivial software are freely available.
We wrote this book for the same reason we wrote TCP/IP Sockets in C: we needed a
resource to support learning net worki ng t hrough pr ogr ammi ng exercises in our courses. Our
goal is to provide a sufficient i nt roduct i on so that st udent s can get their hands on real net work
services wi t hout too much hand-holding. After graspi ng the basics, st udent s can t hen move on
to more advanced assi gnment s, which support learning about routing algorithms, mul t i medi a
protocols, medi um access control, and so on. We have tried to make this book equivalent to
our earlier book to enable i nst ruct ors to allow st udent s to choose the language they use and
still ensure that all st udent s will come away with the same skills and underst andi ng. Of course,
it is not clear that this goal is achievable, but in any case the scope, price, and present at i on
level of the book are i nt ended to be similar.
I nt ended Audi ence
This book is aimed primarily at st udent s in upper-division under gr aduat e or graduat e courses
in comput er networks. It is i nt ended as a suppl ement to a traditional t ext book t hat explains the
probl ems and principles of comput er networks. At the same time, we have tried to make the
ix
X Preface m
book r easonabl y sel f-cont ai ned (except for the assumed pr ogr ammi ng background), so t hat it
can also be used, for example, in courses on operat i ng syst ems or di st r i but ed comput i ng. For
uses out si de the cont ext of a net worki ng course, it will be hel pful if the st udent s have some
acquai nt ance wi t h the basic concept s of net worki ng and TCP/IP.
This book' s ot her t arget audi ence consi st s of pract i t i oners who know Java and want to
l earn about wri t i ng Java appl i cat i ons t hat use TCP/IP. This book shoul d take such user s far
enough t hat t hey can st art exper i ment i ng and l earni ng on t hei r own. Readers are as s umed
to have access to a comput er equi pped wi t h Java. This book is based on Version 1.3 of Java
and the Java Virtual Machine (JVM); however, the code shoul d work wi t h earlier versi ons of
Java, wi t h the except i on of a few new Java met hods. Java is about portability, so the part i cul ar
har dwar e and operat i ng syst em (OS) on whi ch you r un shoul d not mat t er.
Approach
Chapt er 1 provi des a general overview of net worki ng concept s. It is not, by any means, a com-
pl et e i nt roduct i on, but r at her is i nt ended to allow readers to synchroni ze wi t h the concept s and
t er mi nol ogy used t hr oughout the book. Chapt er 2 i nt r oduces the mechani cs of si mpl e clients
and servers; the code in this chapt er can serve as a st art i ng poi nt for a vari et y of exercises.
Chapt er 3 covers the basi cs of message const r uct i on and parsing. The reader who di gest s the
first t hree chapt er s shoul d in principle be able to i mpl ement a client and server for a given
(simple) appl i cat i on protocol. Chapt er 4 t hen deals wi t h t echni ques t hat are necessar y when
bui l di ng mor e sophi st i cat ed and r obust clients and servers. Finally, in keepi ng wi t h our goal
of i l l ust rat i ng pri nci pl es t hr ough pr ogr ammi ng, Chapt er 5 di scusses the rel at i onshi p bet ween
the pr ogr ammi ng const r uct s and the underl yi ng prot ocol i mpl ement at i ons in somewhat mor e
detail.
Our general appr oach i nt roduces pr ogr ammi ng concept s t hr ough si mpl e pr ogr am exam-
ples accompani ed by line-by-line comment ar y t hat descri bes the pur pose of every par t of the
pr ogr am. This lets you see the i mpor t ant obj ect s and met hods as t hey are used in context. As
you l ook at the code, you shoul d be able to under s t and the pur pose of each and every line.
Java makes many t hi ngs easier, but it does not suppor t some funct i onal i t y t hat is
commonl y associ at ed wi t h the C/UNIX socket s i nt erface (asynchronous I/O, select( )-style
multiplexing). In C and C++, the socket i nt erface is a generic appl i cat i on pr ogr ammi ng i nt erface
(API) for all t ypes of prot ocol s, not j ust TCP/IP. Java' s socket classes, on the ot her hand, by
defaul t work exclusively wi t h TCP and UDP over IPv4. Ironically, t here does not seem to be
anyt hi ng in the Java specification or document at i on t hat requi res t hat an i nst ance of the Socket
class use TCP, or t hat a DatagramSoeket i nst ance use UDP. Nevertheless, this book assumes this
to be the case, as is t rue of current i mpl ement at i ons.
Our exampl es do not take advant age of all library facilities in Java. Some of t hese facilities,
in part i cul ar serialization, effectively requi re t hat all communi cat i ng peers be i mpl ement ed in
Java. Also, to i nt roduce exampl es as soon as possible, we want ed to avoid bri ngi ng in a t hi cket of
met hods and cl asses t hat have to be sort ed out later. We have tried to keep it simple, especi al l y
in the early chapt ers.
What This Book Is Not xi
What Thi s Book Is Not
To keep t he pr i ce of t hi s b o o k wi t hi n a r eas onabl e r ange f or a s u p p l e me n t a r y t ext , we have
had to l i mi t i t s s cope and ma i nt a i n a t i ght f ocus on t he goal s out l i ned above. We omi t t e d ma n y
t opi cs a nd di r ect i ons, so it is pr oba bl y wor t h me nt i oni ng s ome of t he t hi ngs t hi s b o o k is not :
It is not an i nt r oduct i on t o Java. We f ocus speci fi cal l y on TCP/ IP s ocket p r o g r a mmi n g
us i ng t he Java l anguage. We expect t hat t he r e a de r i s al r eady acquai nt ed wi t h t he l anguage
and basi c Java l i br ar i es ( especi al l y I/O), and knows how t o devel op p r o g r a ms i n Java.
It is not a b o o k on pr ot ocol s . Readi ng t hi s b o o k will not ma ke you an exper t on IP, TCP,
FTP, HTTP, or any ot her exi st i ng pr ot oc ol ( except ma y b e t he echo pr ot ocol ) . Our f ocus is
on t he i nt er f ace t o t he TCP/ IP ser vi ces pr ovi de d b y t he s ocket abs t r act i on. (It will hel p i f
you s t ar t wi t h s ome i dea a bout tl~e gener al wor ki ngs of TCP and IP, but Chapt er 1 ma y
be a n adequat e subst i t ut e. )
It is not a gui de t o all of J ava' s r i ch col l ect i on of l i br ar i es t hat are des i gned t o hi de
c ommuni c a t i on det ai l s (e.g., HTTPConnection) a nd ma ke t he p r o g r a mme r ' s life easi er.
Since we are t eachi ng t he f unda me nt a l s of how t o do, not how t o avoi d doi ng, pr ot oc ol
devel opment , we do not cover t hes e par t s of t he API. We want r e a de r s to u n d e r s t a n d
pr ot ocol s i n t e r ms of what goes on t he wire, so we mos t l y us e s i mpl e byt e s t r e a ms and
deal wi t h char act er encodi ngs expl i ci t l y. As a cons equence, t hi s t ext does not deal wi t h
U R L , U R L C o n n e c t i o n , and so on. We bel i eve t hat once you u n d e r s t a n d t he pr i nci pl es, us i ng
t hese conveni ence cl asses will be s t r ai ght f or war d. The net wor k- r el evant cl asses t hat we
do cover i ncl ude I net Addr ess, Socket, Ser ver Socket , DatagramPacket, DatagramSoeket, and
Uul t i cas t Socket .
It is not a book on obj ect - or i ent ed desi gn. Our f ocus is on t he i mp o r t a n t pr i nci pl es of
TCP/ IP s ocket pr ogr a mmi ng, and our exampl es ar e i nt e nde d t o i l l ust r at e t h e m conci sel y.
As f ar as possi bl e, we t r y t o adher e t o obj ect - or i ent ed des i gn pr i nci pl es; however , whe n
doi ng so adds compl exi t y t hat obf us c a t e s t he s ocket pr i nci pl es or bl oa t s t he code, we
sacrifice des i gn f or cl ari t y. Thi s t ext does not cover des i gn pa t t e r ns f or net wor ki ng.
( Though we woul d like to t hi nk t hat it pr ovi des s o me of t he b a c k g r o u n d ne c e s s a r y f or
unde r s t a ndi ng s uch pat t er ns! )
It is not a b o o k on wr i t i ng pr oduct i on- qual i t y code. Agai n, t h o u g h we st r i ve f or r obus t ne s s ,
t he pr i ma r y goal of our code e xa mpl e s is educat i on. In or der t o avoi d obs cur i ng t he
pr i nci pl es wi t h l ar ge a mo u n t s of er r or - handl i ng code, we have sacr i f i ced s ome r obus t ne s s
f or br evi t y and cl ari t y.
It is not a book on doi ng your own nat i ve s ocket s i mpl e me nt a t i on i n Java. We f ocus
excl usi vel y on TCP/ IP s ocket s as pr ovi de d by t he s t a nda r d J ava di s t r i but i on and do not
cover t he var i ous s ocket i mp l e me n t a t i o n wr a p p e r cl asses (e.g., Socketlmpl).
To avoi d cl ut t er i ng t he e xa mpl e s wi t h ext r aneous ( nons ocket - r el at ed pr ogr a mmi ng) code,
we have ma de t h e m c omma nd- l i ne based. While t he book' s Web site, www.mkp.com/
practical/javasockets, cont ai ns a f ew e xa mpl e s of GUI - enhanced ne t wor k appl i cat i ons,
we do not i ncl ude or expl ai n t h e m i n t hi s t ext .
X l l Preface u
It is not a b o o k on Java appl et s. Appl et s us e t he s ame J ava net wor ki ng API so t he c ommu-
ni cat i on code s houl d be ver y si mi l ar; however , t her e ar e sever e secur i t y r es t r i ct i ons on
t he ki nds of c ommuni c a t i on an a ppl e t can pe r f or m. We pr ovi de a ver y l i mi t ed di s cus s i on
of t hese r es t r i ct i ons and a si ngl e a ppl e t / a ppl i c a t i on e xa mpl e on t he Web site; however ,
a c ompl e t e des cr i pt i on of appl et net wor ki ng is be yond t he s cope of t hi s t ext .
Thi s b o o k will not ma ke you an e x p e r t - - t h a t t akes year s of exper i ence. However , we hope
it will be us ef ul as a r esour ce, even t o t hos e who al r eady know qui t e a bi t about us i ng s ocket s
in Java. Bot h of us enj oyed wr i t i ng it a nd l ear ned qui t e a bi t al ong t he way.
Acknowledgments
We woul d like t o t ha nk all t he pe opl e who hel ped ma ke t hi s b o o k a real i t y. Despi t e t he book' s
br evi t y, ma n y h o u r s went i nt o r evi ewi ng t he ori gi nal pr opos a l and t he dr af t , and t he r evi ewer s '
i nput has si gni f i cant l y s ha pe d t he fi nal resul t .
First, t ha nks t o t hos e who met i cul ous l y r evi ewed t he dr af t of t he t ext and ma d e sugges-
t i ons f or i mpr ove me nt . These i ncl ude Michel Barbeau, Car l t on Uni versi t y; Chri s Edmonds on-
Yur kanan, Uni ver si t y of Texas at Aust i n, Ted Her man, Uni ver si t y of Iowa; Dave Hol l i nger,
Rens s el aer Pol yt ecni c I nst i t ut e; Ji m Leone, Roches t er I ns t i t ut e of Technol ogy; Dan Schmi dt ,
Texas A&M Uni versi t y; Erick Wagner, EDS; and CSI4321, Spr i ng 2001. Any er r or s t hat r e ma i n
are, of cour se, our r esponsi bi l i t y. We ar e ver y i nt er es t ed in weedi ng out s uch e r r or s i n f ut ur e
pr i nt i ngs so i f you fi nd one, pl eas e emai l ei t her of us. We will ma i nt a i n an er r at a l i st on t he
book' s Web page.
Finally, we are gr at ef ul t o t he f ol ks at Mor gan Kauf mar m. They car e a bout qual i t y a nd
we appr eci at e t hat . We especi al l y appr eci at e t he ef f or t s of Kar yn J ohns on, our edi t or , and Mei
Levenson, our pr oduc t i on coor di nat or .
Feedback
We i nvi t e your s ugges t i ons f or t he i mp r o v e me n t of any a s pe c t of t hi s book. You can s end
f eedback vi a t he book' s Web page, www.mkp.com/practical/javasockets, or you can emai l us at
t he addr es s es bel ow:
Kennet h L. Cal ver t calvert@netlab.uky.edu
Michael J. Dona hoo Jeff_Donahoo@baylor.edu
c hapt er 1
Introduction
Mi l l i o n s of c omput e r s all over t he wor l d are now connect ed to t he wor l dwi de net wor k
known as t he Int ernet . The I nt er net enabl es pr ogr a ms r unni ng on c omput e r s t hous a nds of
mi l es apar t to communi cat e and exchange i nf or mat i on. If you have a c omput e r connect ed to a
net wor k, you may have us e d a Web br ows e r - - a t ypi cal pr ogr a m t hat makes use of t he Int ernet .
What does such a pr ogr a m do to communi cat e wi t h ot her s over a net wor k? The answer vari es
wi t h t he appl i cat i on and t he oper at i ng s ys t em (OS), but a gr eat many pr ogr a ms get access to
net wor k c ommuni c a t i on servi ces t hr ough t he socket s appl i cat i on pr ogr a mmi ng i nt er f ace (API).
The goal of t hi s book is to get you s t ar t ed wr i t i ng Java pr ogr a ms t hat use t he socket s API.
Before del vi ng i nt o t he det ai l s of t he API, it is wor t h t aki ng a br i ef l ook at t he big pi ct ur e
of net wor ks and pr ot ocol s to see how an API for Tr ans mi s s i on Cont r ol Pr ot ocol / I nt er net
Prot ocol fits in. Our goal her e is not to t each you how net wor ks and TCP/IP wor k- - ma ny fine
t ext s are avai l abl e for t hat pur pos e [2, 4, 11, 16, 22J- - but r at her to i nt r oduce some basi c
concept s and t er mi nol ogy.
1.1 Net works, Packets, and Protocol s
A c omput e r net wor k consi st s of machi nes i nt er connect ed by c ommuni c a t i on channel s. We
call t hese machi nes hosts and routers. Host s are c omput e r s t hat r un appl i cat i ons s uch as your
Web br owser . The appl i cat i on pr ogr a ms r unni ng on hos t s are real l y t he us er s of t he net wor k.
Rout er s are machi nes whos e j ob is to relay, or forward, i nf or mat i on f r om one communi cat i on
channel to anot her . They may r un pr ogr a ms but t ypi cal l y do not r un appl i cat i on pr ogr ams . For
our pur pos es , a communication channel is a me a ns of conveyi ng s equences of byt es f r om one
hos t to anot her ; it may be a br oadcas t t echnol ogy like Et hernet , a di al -up mo d e m connect i on,
or s omet hi ng mor e sophi st i cat ed.
Rout er s are i mpor t a nt si mpl y becaus e it is not pr act i cal to connect every hos t di rect l y
to every ot her host . Inst ead, a few hos t s connect to a r out er , whi ch connect s to ot her r out er s,
and so on to f or m t he net wor k. Thi s a r r a nge me nt l et s each machi ne get by wi t h a rel at i vel y
2 Chapter 1: Introduction []
I,,L ]
A
W
Channel
(e.g., Ethernet)
" I
1 ! ( I P ] ' ~ C han n el "~
I I I
L
d , p]
Host Router Host
F i g u r e 1 . 1 : A TCP/IP network.
small number of communi cat i on channels; most host s need only one. Programs t hat exchange
i nf or mat i on over the network, however, do not i nt eract directly with rout ers and generally
remai n blissfully unaware of their existence.
By information we mean sequences of byt es t hat are const ruct ed and i nt erpret ed by pro-
grams. In the cont ext of comput er net works, these byte sequences are generally called packets.
A packet cont ai ns cont rol i nformat i on t hat the net work uses to do its j ob and somet i mes also
i ncl udes user data. An example is i nformat i on identifying the packet ' s destination. Rout ers
use such cont rol i nf or mat i on to figure out how to forward each packet.
A protocol is an agreement about the packet s exchanged by communi cat i ng pr ogr ams
and what t hey mean. A prot ocol tells how packet s are st r uct ur ed- - f or example, where the
dest i nat i on i nf or mat i on is located in the packet and how big it i smas well as how the infor-
mat i on is to be i nt erpret ed. A prot ocol is usual l y desi gned to solve a specific pr obl em usi ng
given capabilities. For example, the HyperText Transfer Protocol (HTTP) solves the pr obl em of
t ransferri ng hypert ext objects bet ween servers, where t hey are stored, and Web browsers t hat
make t hem available to human users.
Impl ement i ng a useful net work requi res t hat a large number of different pr obl ems be
solved. To keep t hi ngs manageabl e and modul ar, different prot ocol s are desi gned to solve
different sets of probl ems. TCP/IP is one such collection of solutions, somet i mes called a
protocol suite. It happens to be the suite of prot ocol s used in the Internet, but it can be used in
st and-al one private net works as well. Hencefort h when we talk about the "network," we mean
any net wor k t hat uses the TCP/IP prot ocol suite. The mai n prot ocol s in the TCP/IP suite are
the Int ernet Protocol (IP), the Tr ansmi ssi on Control Protocol (TCP), and the User Dat agram
Protocol (UDP).
It t urns out to be useful to organi ze prot ocol s into layers; TCP/IP and virtually all
ot her prot ocol suites are organi zed this way. Figure 1.1 shows the rel at i onshi ps among the
prot ocol s, applications, and the socket s API in the host s and rout ers, as well as the flow
of dat a f r om one appl i cat i on (using TCP) to another. The boxes labeled TCP, UDP, and IP
r epr esent i mpl ement at i ons of t hose prot ocol s. Such i mpl ement at i ons typically reside in the
[] 1.2 About Addresses
operat i ng syst em of a host. Applications access the services provi ded by UDP and TCP t hr ough
the sockets API. The arrow depicts the flow of dat a f r om the application, t hr ough the TCP and IP
i mpl ement at i ons, t hr ough the net work, and back up t hr ough the IP and TCP i mpl ement at i ons
at the ot her end.
In TCP/IP, the bot t om layer consi st s of the underl yi ng communi cat i on channel s nf or
example, Et hernet or dial-up modem connect i ons. Those channel s are used by the network
layer, whi ch deals wi t h the pr obl em of forwardi ng packet s t oward their dest i nat i on (i.e., what
rout ers do). The single net wor k layer prot ocol in the TCP/IP suite is the Int ernet Protocol; it
solves the pr obl em of maki ng the sequence of channel s and rout ers bet ween any two host s
look like a single host -t o-host channel.
The Int ernet Protocol provi des a datagram service: every packet is handl ed and delivered
by the net wor k i ndependent l y, like letters or parcels sent via the post al system. To make this
work, each IP packet has to cont ai n the address of its dest i nat i on, j ust as every package t hat
you mail is addr essed to somebody. (We'll say more about addresses shortly.) Al t hough most
delivery compani es guarant ee delivery of a package, IP is only a best-effort protocol: it at t empt s
to deliver each packet, but it can (and occasionally does) lose, reorder, or dupl i cat e packet s in
t ransi t t hr ough the net work.
The layer above IP is called the transport layer. It offers a choice bet ween two protocols:
TCP and UDP. Each bui l ds on the service provi ded by IP, but t hey do so in different ways to
provi de different ki nds of t ransport , whi ch are used by application protocols wi t h different
needs. TCP and UDP have one funct i on in common: addressi ng. Recall t hat IP delivers packet s
to hosts; clearly, a finer granul ari t y of addressi ng is needed to get a packet to a part i cul ar
application, per haps one of many usi ng the net wor k on the same host. Both TCP and UDP
use addresses, called port numbers, to identify appl i cat i ons wi t hi n hosts. They are called end-
to-end transport protocols because they carry dat a all the way from one pr ogr am to anot her
(whereas IP only carries dat a from one host to another).
TCP is desi gned to det ect and recover from the losses, duplications, and ot her errors
t hat may occur in the host -t o-host channel provi ded by IP. TCP provi des a reliable byte-stream
channel, so t hat appl i cat i ons do not have to deal wi t h these probl ems. It is a connection-
oriented protocol: before usi ng it to communi cat e, two pr ogr ams must first est abl i sh a TCP
connection, whi ch involves compl et i ng an exchange of handshake messages bet ween the TCP
i mpl ement at i ons on the two communi cat i ng comput ers. Using TCP is also similar in many ways
to file i nput / out put (I/O). In fact, a file t hat is wri t t en by one pr ogr am and read by anot her is a
reasonabl e model of communi cat i on over a TCP connection. UDP, on the ot her hand, does
not at t empt to recover f r om errors experi enced by IP; it simply ext ends the IP best-effort
dat agr am service so t hat it works bet ween appl i cat i on pr ogr ams i nst ead of bet ween hosts.
Thus, appl i cat i ons t hat use UDP must be pr epar ed to deal wi t h losses, reorderi ng, and so on.
1.2 About Addr esses
When you mail a letter, you provi de the address of the recipient in a f or m t hat the post al
service can under st and. Before you can talk to someone on the phone, you must suppl y their
number to the t el ephone system. In a similar way, before a pr ogr am can communi cat e wi t h
4 Chapter 1: Introduction I
anot her pr ogr am, it mus t tell t he net wor k wher e to find t he ot her pr ogr am. In TCP/IP, it t akes
t wo pi eces of i nf or mat i on to i dent i fy a par t i cul ar pr ogr am: an Internet address, us ed by IP, and
a port number, t he addi t i onal addr es s i nt er pr et ed by t he t r ans por t pr ot ocol (TCP or UDP).
I nt er net addr es s es are 32-bit bi nar y number s . 1 In wri t i ng down I nt er net addr es s es for
h u ma n cons umpt i on (as oppos ed to usi ng t hem i nsi de appl i cat i ons), we t ypi cal l y show t hem
as a st ri ng of f our deci mal number s s epar at ed by per i ods (e.g., 10.1.2.3); t hi s is cal l ed t he
dotted-quad not at i on. The four number s in a dot t ed- quad st ri ng r epr es ent t he cont ent s of t he
f our byt es of t he I nt er net addr es s - - t hus , each is a number bet ween 0 and 255.
One speci al IP addr es s wor t h knowi ng is t he loopback address, 127.0.0.1. This addr es s
is al ways assi gned to a speci al loopback interface, whi ch si mpl y echoes t r ans mi t t ed packet s
ri ght back to t he sender. The l oopback i nt erface is very usef ul for testing; it can be us ed even
when a comput er is not connect ed to t he net work.
Technically, each I nt er net addr es s r ef er s to t he connect i on bet ween a host and an
under l yi ng communi cat i on channel , such as a dial-up mo d e m or Et her net card. Because each
such net wor k connect i on bel ongs to a single host , an I nt er net addr es s i dent i fi es a host as
well as its connect i on to t he net work. However, because a host can have mul t i pl e physi cal
connect i ons to t he net work, one host can have mul t i pl e I nt er net addr esses.
The por t numbe r in TCP or UDP is al ways i nt er pr et ed relative to an I nt er net addr ess.
Ret ur ni ng to our earl i er anal ogi es, a por t number cor r es ponds to a r oom numbe r at a gi ven
st r eet addr ess, say, t hat of a l arge bui l di ng. The post al service uses t he st r eet addr es s to get t he
l et t er to a mailbox; whoever empt i es t he mai l box is t hen r esponsi bl e for get t i ng t he l et t er to t he
pr oper r oom wi t hi n t he bui l di ng. Or consi der a company wi t h an i nt er nal t el ephone syst em:
to speak to an i ndi vi dual in t he company, you first dial t he company' s mai n phone numbe r to
connect to t he i nt er nal t el ephone s ys t em and t hen dial t he ext ensi on of t he par t i cul ar t el ephone
of t he i ndi vi dual t hat you wi sh to speak with. In t hese anal ogi es, t he I nt er net addr es s is t he
st r eet addr es s or t he company' s mai n number , wher eas t he por t cor r es ponds to t he r oom
numbe r or t el ephone ext ensi on. Port number s are 16-bit uns i gned bi nar y number s , so each
one is in t he r ange 1 to 65, 535 (0 is reserved).
1. 3 About Names
Most likely you are accus t omed to r ef er r i ng to host s by name (e.g., host . exampl e. com) . How-
ever, t he I nt er net pr ot ocol s deal wi t h numer i cal addr esses, not names. You shoul d unde r s t a nd
t hat t he use of names i nst ead of addr es s es is a conveni ence f eat ur e t hat is i ndependent of
t he basi c service pr ovi ded by TCP/ I P- - you can wri t e and use TCP/IP appl i cat i ons wi t hout ever
1Throughout this book the term Internet address refers to the addresses used with the current version of
IP, which is version 4 [12]. Because it is expected that a 32-bit address space will be inadequate for future
needs, a new version of IP has been defined [5]; it provides the same service but has much bigger Internet
addresses (128 bits). IPv6, as the new version is known, has not been widely deployed; the sockets API will
require some changes to deal with its much larger addresses [6].
[] 1.4 Clients and Servers
usi ng a name. When you use a name to i dent i f y a communi cat i on endpoi nt , t he s ys t em has to
do some ext r a wor k to resolve t he name i nt o an addr ess.
This ext r a st ep is of t en wor t h it, for a coupl e of r easons. First, na me s are gener al l y
easi er for huma ns to r e me mbe r t han dot t ed- quads . Second, na me s pr ovi de a level of indi-
rect i on, whi ch i nsul at es us er s f r om IP addr es s changes. Dur i ng t he wr i t i ng of t hi s book, t he
Web ser ver for t he publ i s her of t hi s text, Mor gan Kauf mann, changed I nt er net addr es s es
f r om 208. 164. 121. 48 to 216. 200. 143. 124. However, becaus e we r ef er to t hat Web server as
www.mkp.com (clearly muc h easi er to r e me mbe r t han 208. 164. 121. 48) and becaus e t he change
is r ef l ect ed in t he s ys t em t hat ma ps names to addr es s es (www.mkp.com now r esol ves to t he
new I nt er net addr es s i ns t ead of 208. 164. 121. 48), t he change is t r a ns pa r e nt to pr ogr a ms t hat
use t he name to access t he Web server.
The name- r es ol ut i on servi ce can access i nf or mat i on f r om a wi de var i et y of sources. Two
of t he pr i mar y sour ces are t he Domain Name System (DNS) and local conf i gur at i on dat abases.
The DNS [9] is a di s t r i but ed dat abas e t hat ma ps domain names such as www.mkp.com to
I nt er net addr es s es and ot her i nf or mat i on; t he DNS pr ot ocol [10] al l ows hos t s connect ed to
t he I nt er net to ret ri eve i nf or mat i on f r om t hat dat abas e usi ng TCP or UDP. L ocal conf i gur at i on
dat abas es are gener al l y OS-specific me c ha ni s ms for local name- t o- I nt er net addr es s mappi ngs .
1. 4 Cl i ent s and Ser ver s
In our post al and t el ephone anal ogi es, each c ommuni c a t i on is i ni t i at ed by one part y, who sends
a l et t er or makes t he t el ephone call, while t he ot her par t y r e s ponds to t he i ni t i at or ' s cont act by
sendi ng a r e t ur n l et t er or pi cki ng up t he phone and talking. I nt er net c ommuni c a t i on is similar.
The t er ms client and server r ef er to t hese roles: The client pr ogr a m i ni t i at es communi cat i on,
while t he ser ver pr ogr a m wai t s passi vel y for and t hen r e s ponds to cl i ent s t hat cont act it.
Toget her , t he cl i ent and ser ver compos e t he application. The t er ms client and server are
descr i pt i ve of t he t ypi cal si t uat i on in whi ch t he ser ver makes a par t i cul ar capabi l i t y- - f or
exampl e, a dat abas e ser vi ce- - avai l abl e to any cl i ent t hat is able to communi cat e wi t h it.
Whet her a pr ogr a m is act i ng as a cl i ent or ser ver det er mi nes t he gener al f or m of its
use of t he socket s API to est abl i sh c ommuni c a t i on wi t h its peer. (The cl i ent is t he peer of t he
server and vice versa. ) Beyond t hat , t he cl i ent -server di st i nct i on is i mpor t a nt becaus e t he cl i ent
needs to know t he ser ver ' s addr es s and por t initially, but not vice versa. Wi t h t he socket s API,
t he server can, if necessar y, l ear n t he cl i ent ' s addr es s i nf or mat i on whe n it recei ves t he initial
communi cat i on f r om t he client. This is anal ogous to a t el ephone cal l - - i n or der to be called, a
pe r s on does not need to know t he t el ephone numbe r of t he caller. As wi t h a t el ephone call,
once t he connect i on is est abl i shed, t he di st i nct i on bet ween ser ver and cl i ent di sappear s.
How does a client fi nd out a ser ver ' s IP addr es s and por t number ? Usually, t he client
knows t he na me of t he ser ver it wa nt s mf or exampl e, f r om a Universal Resource Locator (URL)
such as http://www. mkp. com--and uses t he name- r es ol ut i on servi ce to l ear n t he cor r es pondi ng
I nt er net addr ess.
Fi ndi ng a ser ver ' s por t numbe r is a di f f er ent story. In pri nci pl e, ser ver s can use any port ,
but t he client mus t be able to l ear n what it is. In t he I nt er net , t her e is a convent i on of assi gni ng
wel l - known por t numbe r s to cer t ai n appl i cat i ons. The I nt er net As s i gned Number Aut hor i t y
6 Chapter 1: Introduction u
(IANA) oversees this assi gnment . For example, port number 21 has been assi gned to the File
Transfer Protocol (FTP). When you r un an FTP client application, it tries to cont act the FTP
server on t hat por t by default. A list of all the assi gned por t number s is mai nt ai ned by the
number i ng aut hori t y of the Int ernet (see http://www.iana.org/assignments/port-numbers).
1. 5 Wh a t Is a Socket ?
A socket is an abst ract i on t hr ough whi ch an appl i cat i on may send and receive data, in much
the same way as an open file handl e allows an appl i cat i on to read and write dat a to stable
storage. A socket allows an appl i cat i on to plug in to the net wor k and communi cat e wi t h ot her
appl i cat i ons t hat are pl ugged in to the same network. Informat i on wri t t en to the socket by
an appl i cat i on on one machi ne can be read by an appl i cat i on on a different machi ne and vice
versa.
Different t ypes of sockets cor r espond to different underl yi ng prot ocol suites and different
stacks of prot ocol s wi t hi n a suite. This book deals only wi t h the TCP/IP prot ocol suite. The
mai n t ypes of sockets in TCP/IP t oday are stream sockets and datagram sockets. St ream socket s
use TCP as the end-t o-end prot ocol (with IP underneat h) and t hus provi de a reliable byte-
st r eam service. A TCP/IP st ream socket represent s one end of a TCP connection. Dat agram
sockets use UDP (again, wi t h IP underneat h) and t hus provi de a best-effort dat agr am service t hat
appl i cat i ons can use to send individual messages up to about 65,500 byt es in length. St ream
and dat agr am sockets are also suppor t ed by ot her prot ocol suites, but this book deals only
wi t h TCP st r eam sockets and UDP dat agr am sockets. A TCP/IP socket is uni quel y identified by
an Int ernet address, an end-t o-end prot ocol (TCP or UDP), and a port number. As you proceed,
you will encount er several ways for a socket to become bound to an address.
Figure 1.2 depicts the logical rel at i onshi ps among applications, socket abst ract i ons,
prot ocol s, and port number s wi t hi n a single host. Note t hat a single socket abst ract i on can
be referenced by mul t i pl e appl i cat i on programs. Each pr ogr am t hat has a reference to a
part i cul ar socket can communi cat e t hr ough t hat socket. Earlier we said t hat a por t identifies
an appl i cat i on on a host. Actually, a port identifies a socket on a host. From Figure 1.2, we see
t hat mul t i pl e pr ogr ams on a host can access the same socket. In practice, separat e pr ogr ams
t hat access the same socket woul d usual l y bel ong to the same appl i cat i on (e.g., mul t i pl e copies
of a Web server program), al t hough in principle they could bel ong to different applications.
1. 6 Exer ci ses
1. Can you t hi nk of a real-life example of communi cat i on t hat does not fit the client-server
model?
2. To how many different ki nds of net works is your home connect ed? How many suppor t
two-way t r anspor t ?
[] 1.6 Exercises
Applications
TCP sockets
TCP ports 1
, - ..... '~ . . . . . -~. uDpSOCketsocketsreferences
. . . . . . . Sockets bound to ports
5535 UDPports
UDP
(" IP ")
Fi g ur e 1. 2: Sockets, protocols, and ports.
3. IP is a best -effort prot ocol , requi ri ng t hat i nf or mat i on be br oken down i nt o dat agr ams,
whi ch may be lost, dupl i cat ed, or r eor der ed. TCP hi des all of this, provi di ng a reliable
service t hat t akes and delivers an unbr oken s t r eam of byt es. How mi ght you go about
pr ovi di ng TCP service on t op of IP? Why woul d anybody use UDP when TCP is available?
c h a p t e r 2
Basic Sockets
You are now ready to learn about writing your own socket applications. We begin by
demonst rat i ng how Java applications identify net work hosts. Then, we describe the creation
of TCP and UDP clients and servers. Java provides a clear distinction bet ween using TCP and
UDP, defining a separate set of classes for bot h protocols, so we treat each separately.
2.1 Socket Addresses
IP uses 32-bit binary addresses to identify communi cat i ng hosts. A client must specify the
IP address of the host runni ng the server program when it initiates communication; the
net work i nfrast ruct ure uses the 32-bit destination address to route the client' s i nformat i on
to the proper machine. Addresses can be specified in Java using a string that contains ei-
ther the dot t ed-quad represent at i on of the numeric address (e.g., 169.1.1.1) or a name (e.g.,
server.example.corn). Java encapsulates the IP addresses abst ract i on in the InetAddress class
which provides three static met hods for creating lnetAddress instances, getByName() and
getAllByName () take a name or IP address and ret urn the correspondi ng InetAddress instance(s).
For example, InetAddress.getByName("192.168.75.13") ret urns an instance identifying the IP
address 192.168.75.13. The third met hod, getLocalHost (), ret urns an InetAddres s instance con-
taining the local host address. Our first program example, InetAddressExample. java, demon-
strates the use of InetAddress. The program takes a list of names or IP addresses as command-
line paramet ers and prints the name and an IP address of the local host, followed by names
and IP addresses of the host s specified on the command line.
I netAdd ressExam pi e. j ava
0 i m p o r t j a v a . n e t . * ; / / f o r I n e t A d d r e s s
1
2 p u b l i c c l a s s I n e t A d d r e s s E x a m p l e {
3
9
! O Chapter 2: Basic Sockets []
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) {
/ / G e t n a m e a n d I P a d d r e s s o f t h e l o c a l h o s t
t r y {
I n e t A d d r e s s a d d r e s s = I n e t A d d r e s s . g e t L o c a l H o s t ( ) ;
S y s t e m . o u t . p r i n t l n ( " L o c a l H o s t : " ) ;
S y s t e m . o u t . p r i n t l n ( " \ t " + a d d r e s s . g e t H o s t N a m e ( ) ) ;
S y s t e m . o u t . p r i n t l n ( " \ t " + a d d r e s s . g e t H o s t A d d r e s s ( ) ) ;
} c a t c h ( U n k n o w n H o s t E x c e p t i o n e ) {
S y s t e m . o u t . p r i n t l n ( " U n a b l e t o d e t e r m i n e t h i s h o s t ' s a d d r e s s " ) ;
}
f o r ( i n t i = O; i < a r g s . l e n g t h ; i + + ) {
/ / G e t n a m e ( s ) / a d d r e s s ( e s ) o f h o s t s g i v e n o n c o m m a n d l i n e
t r y {
I n e t A d d r e s s [ ] a d d r e s s L i s t = I n e t A d d r e s s . g e t A l l B y N a m e ( a r g s [ i ] ) ;
S y s t e m . o u t . p r i n t l n ( a r g s [ i ] + " : " ) ;
/ / P r i n t t h e f i r s t n a m e . A s s u m e a r r a y c o n t a i n s a t l e a s t o n e e n t r y .
S y s t e m . o u t . p r i n t l n ( " \ t " + a d d r e s s L i s t [ O ] . g e t H o s t N a m e ( ) ) ;
f o r ( i n t j = O; j < a d d r e s s L i s t . l e n g t h ; j + + )
S y s t e m . o u t . p r i n t l n ( " \ t " + a d d r e s s L i s t [ j ] . g e t H o s t A d d r e s s ( ) ) ;
} c a t c h ( U n k n o w n H o s t E x c e p t i o n e ) {
S y s t e m . o u t . p r i n t l n ( " U n a b l e t o f i n d a d d r e s s f o r " + a r g s [ i ] ) ;
}
InetAddressExample.java
1. Pri nt i nf or mat i on about t he local host : lines 6-14
9 Creat e an InetAddress i nst ance for t he local host : line 8
9 Pri nt t he local host i nf or mat i on: lines 9-11
getH0stName() and getH0stAddress() r et ur n a string for the host name and IP address,
respectively.
2. Request i nf or mat i on for each host speci fi ed on t he c omma nd line: lines 16-28
9 Creat e an ar r ay of InetAddress i nst ances for t he speci fi ed host : line 19
TnetAddress.getAllByName() r et ur ns an array of InetAddress i nst ances, one for each
of the specified host ' s addresses.
9 Pri nt t he host i nf or mat i on: lines 22-24
To use this appl i cat i on to find i nf or mat i on about the local host and the publ i sher' s Web server
(www.mkp.com), do the following:
[] 2.1 Socket Addresses ! !
% java InetAddressExample www.mkp.com
Local Host:
t r act or . f ar m. com
169. 1. 1. 2
www.mkp.com:
www.mkp.com
216.200.143.124
If we know t he IP addr es s of a hos t (e.g., 169.1.1.1), we fi nd t he name of t he hos t by
% j a v a I n e t A d d r e s s E x a m p l e 169. i. i. 1
L o c a l H o s t :
t r a c t o r , f a r m . c o m
169. 1. 1. 2
169. 1. 1. 1:
b a s e . f a r m . c o m
169. 1. I . i
W h e n t h e n a m e s e r v i c e is n o t a v a i l a b l e f o r s o m e r e a s o n - - s a y , t h e p r o g r a m is r u n n i n g o n
a machi ne t hat is not connect ed to any ne t wor k- - a t t e mpt i ng to i dent i f y a hos t by name may
fail. Moreover, it may t ake a si gni fi cant a mount of t i me to do so, as t he s ys t em t ri es var i ous
ways to r esol ve t he na me to an IP addr ess. It is t her ef or e good t o know t hat you can al ways
r ef er to a hos t usi ng t he IP addr es s in dot t ed- quad not at i on. In any of our exampl es, if a r emot e
hos t is speci fi ed by name, t he hos t r unni ng t he exampl e mus t be conf i gur ed to conver t names
to addr esses, or t he exampl e won' t work. If you can pi ng a hos t usi ng one of its names (e.g.,
r un t he c omma nd "pi ng server.example.corn"), t hen t he exampl es s houl d wor k wi t h names. If
your pi ng t est fails or t he exampl e hangs, t ry speci f yi ng t he hos t by IP addr ess, whi ch avoi ds
t he name- t o- addr es s conver s i on al t oget her .
I n e t A d d r e s s 1
Cr e a t o r s
st at i c I net Addr es s [ ] getAllByName(String host)
Ret ur ns t he list of addr es s es for t he speci fi ed host .
host Host name or addr es s
1For each Java networking class described in this text, we present only the primary met hods and omit
methods that are deprecated or whose use is beyond the scope of this text. As with everything in Java,
the specification is a moving target. This information is included to provide an overall picture of the Java
socket interface, not as a final authority. We encourage the reader to refer to the API specifications from
java.sun.com as the current and definitive source.
! 2 Chapter 2: Basic Sockets []
static Inet Address getByName(String host)
static Inet Address getLocalHost0
Returns an IP address for the specified/local host.
host Host name or IP address
Accessors
byt e[ ] getAddress0
Returns the 4 bytes of the 32-bit IP address in big-endian order.
String getHostAddress()
Returns the IP address in dot t ed-quad not at i on (e.g., "169.1.1.2").
String getHostName()
Returns the canonical name of the host associated with the address.
bool e an isMulticastAddress()
Returns t rue if the address is a multicast address (see Section 4.3.2).
Oper at or s
bool e an equals(Object address)
Returns t rue if address is non-null and represent s the same address as this $netAddress
instance.
address Address to compare
2 . 2 TCP So c k e t s
Java provides two classes for TCP: Socket and ServerSocket. An instance of Socket represent s
one end of a TCP connection. A TCP connection is an abstract two-way channel whose ends
are each identified by an IP address and port number. Before being used for communication,
a TCP connection must go t hrough a setup phase, which starts with the client' s TCP sending a
connect i on request to the server' s TCP. An instance of ServerSocket listens for TCP connection
request s and creates a new Socket instance to handle each incoming connection.
2.2.1 TCPCl i ent
The client initiates communi cat i on with a server that is passively waiting to be contacted. The
typical TCP client goes t hrough three steps:
1. Const ruct an instance of Socket: The const ruct or establishes a TCP connection to the
specified remot e host and port.
[] 2.2 TCP Sockets 1 3
2. Communi cat e usi ng t he socket ' s I/O st reams: A connect ed i nst ance of Socket cont ai ns
an Input St ream and 0ut put St ream t hat can be us ed j ust like any ot her Java I/O st r eam (see
Chapt er 3).
3. Close t he connect i on usi ng t he cl ose( ) met hod of Socket.
Our first TCP appl i cat i on, called TCPEchoClient. java, is a client t hat communi cat es wi t h an
e c ho s e r v e r usi ng TCP. An echo server si mpl y r epeat s what ever it recei ves back to the client.
The st ri ng to be echoed is pr ovi ded as a command- l i ne ar gument to our client. Many syst ems
i ncl ude an echo server for debuggi ng and t est i ng pur poses. To t est if t he s t andar d echo server
is runni ng, try t el net t i ng to por t 7 (the defaul t echo port ) on t he server (e.g., at command line
"t el net ser ver , example, corn 7" or use your basic t el net application).
TCPEchoClient.java
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
31
0 i m p o r t j a v a . n e t . * ; / / f o r S o c k e t
1 i m p o r t j a v a . i o . * ; / / f o r l O E x c e p t i o n a n d I n p u t / O u t p u t S t r e a m
2
3 p u b l i c c l a s s r C P E c h o C l i e n t {
4
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s I O E x c e p t i o n {
i f ( ( a r g s . l e n g t h < 2) II ( a r g s . l e n g t h > 3 )) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < S e r v e r > < W o r d > [ < P o r t > ] " ) ;
S t r i n g s e r v e r = a r g s [ 0 ] ; / / S e r v e r n a m e o r I P a d d r e s s
/ / C o n v e r t i n p u t S t r i n g t o b y t e s u s i n g t h e d e f a u l t c h a r a c t e r e n c o d i n g
b y t e [ ] b y t e B u f f e r = a r g s [ l ] . g e t B y t e s ( ) ;
i n t s e r v P o r t = ( a r g s . l e n g t h = = 3) ? I n t e g e r . p a r s e l n t ( a r g s [ 2 ] ) : 7;
/ / C r e a t e s o c k e t t h a t i s c o n n e c t e d t o s e r v e r o n s p e c i f i e d p o r t
S o c k e t s o c k e t = n e w S o c k e t ( s e r v e r , s e r v P o r t ) ;
S y s t e m . o u t . p r i n t l n ( " C o n n e c t e d t o s e r v e r . . . s e n d i n g e c h o s t r i n g " ) ;
I n p u t S t r e a m i n = s o c k e t , g e t l n p u t S t r e a m ( ) ;
O u t p u t S t r e a m o u t = s o c k e t , g e t O u t p u t S t r e a m ( ) ;
o u t . w r i t e ( b y t e B u f f e r ) ; / / S e n d t h e e n c o d e d s t r i n g t o t h e s e r v e r
/ / R e c e i v e t h e s a m e s t r i n g b a c k f r o m t h e s e r v e r
i n t t o t a l B y t e s R c v d = 0; / / T o t a l b y t e s r e c e i v e d s o f a r
i n t b y t e s R c v d ; / / B y t e s r e c e i v e d i n l a s t r e a d
w h i l e ( t o t a l B y t e s R c v d < b y t e B u f f e r . l e n g t h ) {
i f ( ( b y t e s R c v d = i n . r e a d ( b y t e B u f f e r , t o t a l B y t e s R c v d ,
b y t e B u f f e r . l e n g t h - t o t a l B y t e s R c v d ) ) = = -I )
t h r o w n e w S o c k e t E x c e p t i o n ( " C o n n e c t i o n c l o s e d p r e m a t u r e l y " ) ;
14 Chapter 2: Basic Sockets m
32
33
34
35
36
37
38
39
}
}
t o t a l B y t e s R c v d + = b y t e s R c v d ;
}
S y s t e m . o u t . p r i n t l n ( " R e c e i v e d : " + n e w S t r i n g ( b y t e B u f f e r ) ) ;
s o c k e t . c l o s e ( ) ; / / C l o s e t h e s o c k e t a n d i t s s t r e a m s
TCP Ec hoCI i e nt . j a v a
1. Appl i cat i on set up and paramet er parsi ng: lines 0-14
[] Convert the echo string: line 12
TCP sockets send and receive sequences of bytes. The get Byt es() met hod of St ri ng
ret urns a byte array represent at i on of the string. (See Section 3.1 for a di scussi on of
charact er encodings.)
[] Det ermi ne the port of the echo server: line 14
The default echo port is 7. If we specify a third paramet er, I nt eger . par s eI nt ( ) takes
the string and ret urns the equivalent integer value.
2. TCP s ocket creation: line 17
The Socket const ruct or creates a socket and establishes a connect i on to the specified
server, identified either by name or IP address. Note t hat the underl yi ng TCP deals only
wi t h IP addresses. If a name is given, the i mpl ement at i on resolves it to the correspond-
ing address. If the connect i on at t empt fails for any reason, the const ruct or t hrows an
l O B x c e p t i o n .
3. Get s ocket i nput and out put streams: lines 20-21
Associ at ed with each connect ed Socket instance is an InputStream and 0utputStream. We
send dat a over the socket by writing bytes to the 0utputStream j ust as we would any other
stream, and we receive by reading from the InputStream.
4. Send the stri ng to echo server: line 23
The wr i t e( ) met hod of 0utputStream t ransmi t s the given byte array over the connect i on
to the server.
5. Recei ve the repl y f rom the echo server: lines 25-33
Since we know the number of bytes to expect from the echo server, we can repeat edl y
receive byt es until we have received the same number of bytes we sent. This particular
form of read() takes three paramet ers: 1) buffer to receive into, 2) byte offset into the
buffer where the first byte received shoul d be placed, and 3) the maxi mum number of
byt es to be pl aced in the buffer, read() blocks until some dat a is available, reads up
to the specified maxi mum number of bytes, and ret urns the number of bytes actually
pl aced in the buffer (which may be less t han the given maximum). The loop simply fills
[] 2.2 TCP Sockets 1 5
up byteBuffer until we receive as many bytes as we sent. If the TCP connection is closed by
the other end, read() ret urns -1. For the client, this indicates that the server premat urel y
closed the socket.
Why not j ust a single read? TCP does not preserve read() and wr i t e( ) message
boundaries. That is, even t hough we sent the echo string with a single wr i t e( ) , the echo
server may receive it in multiple chunks. Even if the echo string is handl ed in one chunk
by the echo server, the reply may still be broken into pieces by TCP. One of the most
common errors for beginners is the assumpt i on that data sent by a single wr i t e( ) will
always be received in a single read ().
6. Print echoed string: line 35
To print the server' s response, we must convert the byte array to a string using the default
character encoding.
7. Close socket: line 37
When the client has finished receiving all of the echoed data, it closes the socket.
We can communi cat e with an echo server named server.example.com with IP address
169.1.1.1 in either of the following ways:
% j a v a T C P E c h o C l i e n t s e r v e r . e x a m p l e . c o m " E c h o t h i s !"
R e c e i v e d : E c h o t h i s !
% j a v a T C P E c h o C l i e n t 169. i. i. 1 " E c h o t h i s !"
R e c e i v e d : E c h o t h i s !
S e e T C P E c h o C l i e n t G U I . j a v a o n t h e b o o k ' s W e b s i t e f o r a n i m p l e m e n t a t i o n o f t h e T C P e c h o c l i e n t
with a graphical interface.
Socket
Co n s t r u c t o r s
Socket(InetAddress remoteAddr, int remotePort)
Socket(String remoteHost, int remotePort)
Socket(InetAddress remoteAddr, int remotePort, Inet Address localAddr, int localPort)
Socket(String remoteHost, int remotePort, Inet Address localAddr, int localPort)
Constructs a TCP socket connect ed to the specified remot e address and port. The first
two forms of the const ruct or do not specify the local address and port, so a default
local address and some available port are chosen. Specifying the local address may be
useful on a host with multiple interfaces.
remoteAddr Remote host address
remoteHost Remote host name or IP address (in dot t ed-quad form)
remotePort Remote port
16 Chapter 2: Basic Sockets []
l ocal Addr
localPort
Local address; use n u l l to specify using the default local
address
Local port; a localPort of 0 allows the const ruct or to pick any
available port
Op e r a t o r s
voi d close()
Closes the TCP socket and its I/O streams.
voi d shutdownTnput()
Closes the i nput side of a TCP stream. Any unread data is silently discarded, including
dat a buffered by the socket, dat a in transit, and dat a arriving in the future. Any subse-
quent at t empt to read from the socket will ret urn end-of-st ream (-1); any subsequent
call to get l nput St ream() will cause an l O E x c e p t i o n to be t hrown (see Section 4.5).
voi d shutdown0utput()
Closes the out put side of a TCP stream. The i mpl ement at i on will at t empt to deliver any
dat a already wri t t en to the socket' s out put st ream to the other end. Any subsequent
at t empt to write to the socket' s out put st ream or to call get0utputStream() will cause
an IOException to be t hrown (see Section 4.5).
Accessors/Mutators
InetAddress getlnetAddress()
int getPort()
Ret urns the remot e socket address/ port .
InputStream getlnputStream0
OutputStream get0utputStream0
Returns a st ream for readi ng/ wri t i ng bytes f r om/ t o the socket.
bool ean ge t K e e p A l i v e ()
voi d setKeepAlive(boolean on)
Ret ur ns/ set s keepalive message behavior. If keepalive is enabled, TCP sends a probe
to the ot her end of the connect i on when no dat a has been exchanged for a system-
dependent amount of time (usually two hours). If the remot e socket is still alive, it
will acknowledge the probe (invisible to the application). However, if the other end
fails to acknowledge several probes in a row, the local TCP closes the connection, and
subsequent operat i ons on it will t hrow an exception. Keepalive is disabled by default.
on If t rue (false), enable (disable) keepalive.
[] 2.2 TCP Sockets |
InetAddress g e t L o c a l A d d r e s s ( )
int g e t L o c a l P o r t ( )
R e t u r n s t h e l o c a l s o c k e t a d d r e s s / p o r t .
int g e t R e c e i v e B u f f e r S i z e ( )
int g e t S e n d B u f f e r S i z e ( )
v o i d s e t R e c e i v e B u f f e r S i z e ( i n t s i z e )
v o i d s e t S e n d B u f f e r S i z e ( i n t s i z e )
R e t u r n s / s e t s t h e s i z e o f t h e s e n d / r e c e i v e b u f f e r f o r t h e s o c k e t ( s e e S e c t i o n 4.4).
si ze Number of bytes to allocate for the socket send/ recei ve
buffer
int getSoLinger()
voi d set SoLi nger(bool ean on, int l i nger)
Ret ur ns/ set s the maxi mum amount of time (in milliseconds) t hat cl ose() will block
waiting for all dat a to be delivered, getSoLinger() ret urns -1 if lingering is disabled
(see Section 5.4). Lingering is off by default.
on If true, the socket lingers on cl ose(), up to the maxi mum
specified time.
l i nger The maxi mum amount of time (milliseconds) a socket lingers
o n c l o s e ( )
int getSoTimeout()
voi d setSoTimeout(int t i meout )
Ret ur ns/ set s the maxi mum amount of time t hat a read() on this socket will block. If
the specified number of milliseconds elapses before any dat a is available, an I nt er -
ruptedIOException is t hrown (see Section 4.2).
t i meout The maxi mum time (milliseconds) to wait for dat a on a
read(). The value 0 (the default) indicates t hat there is no
time limit, meani ng t hat a read will not ret urn until dat a is
available.
bool ean g e t T c p N o D e l a y ( )
voi d s e t T c p N o D e l a y ( b o o l e a n o n )
R e t u r n s / s e t s w h e t h e r t h e N a g l e a l g o r i t h m t o c o a l e s c e T C P p a c k e t s is d i s a b l e d . T o a v o i d
small TCP packets, which make inefficient use of net work resources, Nagle' s al gori t hm
(enabled by default) delays packet t ransmi ssi on under certain conditions to i mprove
the opport uni t i es to coalesce bytes from several writes into a single TCP packet. This
delay is unaccept abl e to some types of interactive applications.
on If t rue (false), disable (enable) Nagle' s algorithm.
1 8 Chapter 2: Basic Sockets m
Caveat: By default, Socket is i mpl ement ed on top of a TCP connection; however, in Java,
you can actually change the underlying i mpl ement at i on of Socket. This book is about TCP/IP,
so for simplicity we assume that the underlying i mpl ement at i on for all of the these net worki ng
classes is the default.
2.2.2 TCP Server
We now t urn our at t ent i on to constructing a server. The server' s job is to set up a communi-
cation endpoi nt and passively wait for connections from clients. The typical TCP server goes
t hrough two steps:
1. Const ruct a ServerSocket instance, specifying the local port. This socket listens for
incoming connections to the specified port.
2. Repeatedly:
9 Call the accept () met hod of ServerSocket to get the next incoming client connection.
Upon est abl i shment of a new client connection, an instance of Socket for the new
connection is created and ret urned by accept ().
9 Communi cat e with the client using the ret urned Socket's InputStream and Output-
Stream.
9 Close the new client socket connection using the cl ose() met hod of Socket.
Our next example, TCPEchoServer. java, i mpl ement s the echo service used by our client
program. The server is very simple. It runs forever, repeatedly accepting a connection, receiving
and echoing bytes until the connection is closed by the client, and t hen closing the client socket.
TCPEchoServer.java
0 import j ava. net . * ; / / for Socket, ServerSocket, and InetAddress
1 import j ava. i o. *; / / for IOException and Input/0utputStream
2
3 public class TCPEchoServer {
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
p r i v a t e s t a t i c f i n a l i n t B U F S I Z E = 32; / / S i z e o f r e c e i v e b u f f e r
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s l O E x c e p t i o n {
i f ( a r g s . l e n g t h != i) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < P o r t > " ) ;
i n t s e r v P o r t = I n t e g e r . p a r s e l n t ( a r g s [0 ] ) ;
/ / C r e a t e a s e r v e r s o c k e t t o a c c e p t c l i e n t c o n n e c t i o n r e q u e s t s
S e r v e r S o c k e t s e r v S o c k = n e w S e r v e r S o c k e t ( s e r v P o r t ) ;
i n t r e c v M s g S i z e ; / / S i z e o f r e c e i v e d m e s s a g e
b y t e [ ] b y t e B u f f e r = n e w b y t e [ B U F S l Z E ] ; / / R e c e i v e b u f f e r
m 2.2 TCP Sockets 1 9
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
}
}
f o r ( ; ; ) { / / R u n f o r e v e r , a c c e p t i n g a n d s e r v i c i n g c o n n e c t i o n s
S o c k e t c l n t S o c k = s e r v S o c k . a c c e p t ( ) ; / / G e t c l i e n t c o n n e c t i o n
S y s t e m . o u t . p r i n t l n ( " H a n d l i n g c l i e n t a t " +
c l n t S o c k . g e t I n e t A d d r e s s ( ) . g e t H o s t A d d r e s s ( ) + " o n p o r t " +
c l n t S o c k , g e t P o r t ()) ;
I n p u t S t r e a m i n = c l n t S o c k , g e t l n p u t S t r e a m ( ) ;
O u t p u t S t r e a m o u t = c l n t S o c k . g e t O u t p u t S t r e a m ( ) ;
/ / R e c e i v e u n t i l c l i e n t c l o s e s c o n n e c t i o n , i n d i c a t e d b y - i r e t u r n
w h i l e ( ( r e c v M s g S i z e = i n . r e a d ( b y t e B u f f e r ) ) != -I )
o u t . w r i t e ( b y t e B u f f e r , O, r e c v M s g S i z e ) ;
c l n t S o c k , c l o s e () ;
}
/ * N O T R E A C H E D * /
/ / C l o s e t h e s o c k e t . We a r e d o n e w i t h t h i s c l i e n t !
TCPEchoServer.java
1. Appl i cat i on setup and par amet er parsi ng: lines 0-12
2. Server socket creation: line 15
servSock listens for client connect i on request s on the port specified in the constructor.
3. Loop forever, i t erat i vel y handl i ng i ncomi ng connect i ons" lines 20-35
9 Accept an i ncomi ng connect i on: line 21
The sole purpose of a ServerSocket instance is to supply a new, connect ed Socket
i nst ance for each new TCP connection. When the server is ready to handle a client, it
calls accept (), which blocks until an incoming connect i on is made to the ServerSocket' s
port. accept () t hen ret urns an instance of Socket that is already connected to the
remot e socket and ready for reading and writing.
9 Report connect ed client: lines 23-25
We can query the newly creat ed Socket instance for the address and port of the
connecting client. The get l net Address() met hod of Socket ret urns an instance of
InetAddress containing the address of the client. We call getHostAddress() to ret urn
the IP address as a dot t ed-quad String. The get Por t ( ) met hod of Socket ret urns the
port of the client.
9 Get socket input and output st reams: lines 27-28
Bytes wri t t en to this socket' s 0utputStream will be read from the client' s socket' s
InputStream, and bytes wri t t en to the client' s 0utputStream will be read from this
socket' s InputStream.
20 Chapter 2: Basic Sockets []
9 Recei ve and repeat data unt i l t he cl i ent cl oses: l i nes 30- 32
The while loop repeat edl y reads bytes (when available) from the i nput st r eam and
i mmedi at el y writes the same bytes back to the out put st ream until the client closes
the connection. The read() met hod of InputStream reads up to the maxi mum number
of byt es the array can hold (in this case, BUFSIZE bytes) into the byte array (byteBuffer)
and ret urns the number of bytes read. read () blocks until dat a is available and ret urns
-1 if there is no dat a available, indicating t hat the client closed its socket. In the echo
protocol, the client closes the connect i on when it has received the number of byt es
back t hat it sent, so in the server we expect to receive a -1 from read(). Recall t hat in
the client, receiving a -1 from read() indicates an error because it indicates t hat the
server pr emat ur el y closed the connection.
As previously ment i oned, read() does not have to fill the entire byte array to
return. In fact, it can ret urn after having read only a single byte. The wr i t e( ) met hod
of 0utputStream writes recvMsgSize bytes from byteBuffer to the socket. The second
par amet er indicates the offset into the byte array of the first byte to send. In this case,
0 indicates to take byt es starting from the front of byteBuffer. If we had used the
form of wr i t e( ) t hat takes only the buffer argument , all the byt es in the buffer array
woul d have been t ransmi t t ed, possibly including bytes t hat were not received from
the client!
9 Cl ose cl i ent socket : line 34
Ser ver Socket
C o n s t r u c t o r s
ServerSocket(int localPort)
ServerSocket(int localPort, int queueLimit)
ServerSocket(int localPort, i nt queueLimit, I net Addres s localAddr)
Const ruct a TCP socket t hat is ready to accept incoming connect i ons to the specified
local port. Optionally, the size of the connect i on queue and the local address can be
set.
localPort Local port. A port of 0 allows the const ruct or to pick any
available port.
queueLimit The maxi mum size of the queue of i ncompl et e connect i ons
and sockets waiting to be accept ()ed. If a client connect i on
request arrives when the queue is full, the connect i on is
refused. Note t hat this may not necessarily be a hard lirrdt.
For most pl at forms, it cannot be used to precisely control
client population.
m 2.2 TCP Sockets 21
l ocal Addr The IP address to which connections to this socket should be
addressed (must be one of the local interface addresses). If the
address is not specified, the socket will accept connections to
any of the host ' s IP addresses. This may be useful for host s
with multiple interfaces where the server socket should only
accept connections on one of its interfaces.
Operators
Socket a c c e p t ( )
R e t u r n s a c o n n e c t e d S o c k e t i n s t a n c e f o r t h e n e x t n e w i n c o m i n g c o n n e c t i o n t o t h e
s e r v e r s o c k e t . If n o e s t a b l i s h e d c o n n e c t i o n is w a i t i n g , a c c e p t ( ) b l o c k s u n t i l o n e is
e s t a b l i s h e d o r a t i m e o u t o c c u r s ( s e e s e t S o T i m e o u t ( ) ) .
v o i d c l o s e ()
C l o s e s t h e u n d e r l y i n g T C P s o c k e t . A f t e r i n v o k i n g t h i s m e t h o d , i n c o m i n g c l i e n t c o n -
n e c t i o n r e q u e s t s f o r t h i s s o c k e t a r e r e j e c t e d .
Accessors/Mutators
Inet Address getlnetAddress ()
int getLocalPort()
Returns the local addr ess/ por t of the server socket.
int g e t S o T i m e o u t O
voi d s e t S o T i m e o u t ( i n t t i meout )
Ret urns/ set s the maxi mum amount of time (in milliseconds) that an accept () will
block for this socket. If the timer expires before a connection request arrives, an
InterruptedlOException is thrown. A t i meout value of 0 indicates no timeout: calls
to accept () will not ret urn until a new connection is available, regardless of how much
time passes (see Section 4.2).
2. 2. 3 I nput and Out put Streams
As illustrated by the examples above, the pri mary paradi gm for I/O in Java is the st ream
abstraction. A st ream is simply an ordered sequence of bytes. Java i nput st reams support
reading bytes, and out put st reams support writing bytes. In our TCP client and server, each
Socket instance holds an InputStream and an 0utputStream instance. When we write to the
out put st ream of a Socket, the bytes can (eventually) be read from the i nput st ream of the
Socket at the other end of the connection.
0utputStream is the abstract superclass of all out put st reams in Java. Using an Output-
Stream, we can write bytes to, flush, and close the out put stream.
22 Chapter 2: Basic Sockets II
OutputStream
data
offset
length
v o i d flush()
abs t ract v o i d wri t e(i nt data)
Writes a single byte to the out put stream.
data Byte (low-order 8 bits) to write to out put st ream
v o i d wri t e(byt e[ ] data)
Writes entire array of bytes to the out put stream.
data Bytes to write to out put st ream
v o i d wri t e(byt e[ ] data, int offset, int length)
Writes length byt es from data starting from byte offset.
Bytes from which to write to out put st ream
Starting byte to send in data
Number of bytes to send
Pushes any buffered data out to the stream.
v o i d close()
Termi nat es the stream.
I n p u t S t r e a m is the abst ract superclass of all i nput streams. Using an I n p u t S t r e a m , we can
read byt es from and close the i nput stream.
InputStream
abst r act int read()
Read and ret urn a single byte from the i nput stream. The byte read is in the least
significant byte of the ret urned integer. This met hod ret urns -1 on end-of-stream.
i nt read(byt e[] data)
Reads up to data.length bytes (or until the end-of-stream) from the i nput st r eam into
data and ret urns the number of bytes read. If no dat a is available, read () blocks until
at least I byte can be read or the end-of-st ream is detected, indicated by a ret urn of -1.
data Buffer to receive dat a from i nput st ream
int read(byte[ ] data, int offset, i nt length)
Reads up to length bytes (or until the end-of-stream) from the i nput st ream into
data, starting at posi t i on offset, and ret urns the number of bytes read. If no dat a
[] 2.3 UDP Sockets 23
is available, read() blocks until at least 1 byte can be read or the end-of-stream is
detected, indicated by a ret urn of -1.
data Buffer to receive data from input st ream
offset Starting byte of data in which to write
length Maximum number of bytes to read
int a v a i l a b l e ( )
R e t u r n s t h e n u m b e r o f b y t e s a v a i l a b l e f o r i n p u t .
v o i d c l o s e ()
T e r m i n a t e s t h e s t r e a m .
2. 3 UDP Socket s
UDP provides an end-to-end service different from that of TCP. In fact, UDP performs only
two functions: 1) it adds anot her layer of addressing (ports) to that of IP, and 2) it detects
data corrupt i on that may occur in transit and discards any corrupt ed messages. Because of
this simplicity, UDP sockets have some different characteristics from the TCP sockets we saw
earlier. For example, UDP sockets do not have to be connect ed before being used. Where TCP
is analogous to telephone communication, UDP is analogous to communi cat i ng by mail: you
do not have to "connect" before you send a package or letter, but you do have to specify
the destination address for each one. Similarly, each message--cal l ed a datagram--carries its
own address i nformat i on and is i ndependent of all others. In receiving, a UDP socket is like
a mailbox into which letters or packages from many different sources can be placed. As soon
as it is created, a UDP socket can be used to send/receive messages t o/ f r om any address and
t o/ f r om many different addresses in succession.
Another difference bet ween UDP sockets and TCP sockets is the way that they deal with
message boundaries: UDP sockets preserve them. This makes receiving an application message
simpler, in some ways, t han it is with TCP sockets. (This is discussed furt her in Section 2.3.4.) A
final difference is that the end-to-end t ransport service UDP provides is best-effort: there is no
guarantee that a message sent via a UDP socket will arrive at its destination, and messages can
be delivered in a different order t han they were sent Oust like letters sent t hrough the mail).
A program using UDP sockets must therefore be prepared to deal with loss and reordering.
(We'll provide an example of this later.)
Given this additional burden, why would an application use UDP instead of TCP? One
reason is efficiency: if the application exchanges only a small amount of dat a--say, a single
request message from client to server and a single response message in the other direction--
TCP's connection est abl i shment phase at least doubles the number of messages (and the
number of round-t ri p delays) requi red for the communication. Another reason is flexibility:
when somet hi ng other t han a reliable byt e-st ream service is required, UDP provides a minimal-
overhead pl at form on which to i mpl ement whatever is needed.
Java programmers use UDP sockets via the classes DatagramPacket and DatagramSocket.
Both clients and servers use DatagramSockets to send and receive DatagramPackets.
24 Chapter 2: Basic Sockets []
2.3.1 DatagramPacket
Instead of sending and receiving st reams of bytes as with TCP, UDP endpoi nt s exchange
self-contained messages, called datagrams, which are represent ed in Java as instances of
DatagramPacket. To send, a Java program constructs a DatagramPacket instance and passes it as
an argument to the send() met hod of a DatagramSocket. To receive, a Java program const ruct s
a DatagramPacket instance with preallocated space (a byte[ ]), into which the cont ent s of a
received message can be copied (if/when one arrives), and then passes the instance to the
recei ve () met hod of a DatagramSocket.
In addition to the data, each instance of DatagramPacket also contains address and port
information, the semantics of which depend on whet her the dat agram is being sent or received.
When a DatagramPacket is sent, the address and port identify the destination; for a received
DatagramPacket, they identify the source of the received message. Thus, a server can receive
into a DatagramPacket instance, modify its buffer contents, t hen send the same instance, and
the modified message will go back to its origin. Internally, a DatagramPacket also has length
and offset fields, which describe the location and number of bytes of message data inside the
associated buffer. See the following reference and Section 2.3.4 for some pitfalls to avoid when
usi ng DatagramPackets.
Dat ag r am Packet
Co n s t r u c t o r s
DatagramPacket(byte[ ] buffer, int length)
DatagramPacket(byte[ ] buffer, int offset, int length)
DatagramPacket(byte[ ] buffer, int length, Inet Address remoteAddr, int remotePort)
DatagramPacket(byte[] buffer, int offset, int length, Inet Address remoteAddr, int re-
motePort)
Constructs a dat agram and makes the given byte array its data buffer. The first two
forms are typically used to const ruct DatagramPackets for receiving because the desti-
nat i on address is not specified (although it could be specified later with setAddress()
and set Port ()). The second two forms are typically used to construct DatagramPackets
for sending.
buffer Datagram payload
length Number of bytes of the buffer that will actually be used.
If the dat agram is sent, length bytes will be transmitted. If
receiving into this datagram, length specifies the maxi mum
number of bytes to be placed in the buffer.
offset Location in the buffer array of the first byte of message data
to be sent/received; defaults to 0 if unspecified.
[] 2.3 UDP Sockets 2 5
remoteAddr
remotePort
Address (typically destination) of the datagram
Port (typically destination) of the datagram
Accessors/ Mutators
I net Addres s getAddress()
voi d setAddress(InetAddress address)
Returns/sets the datagram address. There are other ways to set the address: 1) the
address of a DatagramPacket instance can also be set by the constructor, and 2)
the recei ve() met hod of DatagramSocket sets the address to the datagram sender' s
address.
address Datagram address
i nt getPort()
voi d setPort(int port)
Returns/sets the datagram port. There are other ways to set the address: 1) the port
can be explicitly set by the constructor or the set Port () method, and 2) the recei ve()
met hod of DatagramSocket sets the port to the datagram sender' s port.
port Datagram port
i nt getT.ength()
voi d setLength(int length)
Returns/sets the internal length of the datagram. The internal datagram length can be
set explicitly by the constructor or by the setLength() method. Attempting to make it
larger than the length of the associated buffer results in an IllegalArgumentException.
The recei ve() met hod of DatagramSocket uses the internal length in two ways: 1) on
input, it specifies the maximum number of bytes of a received message that will be
copied into the buffer, and 2) on return, it indicates the number of bytes actually placed
in the buffer.
length Length in bytes of the usable portion of the buffer
i nt get0ffset()
Returns the location in the buffer of the first byte of data to be sent/received. There
is no set 0f f set ( ) method; however, it can be set with setData().
byte[] getDataO
Returns the buffer associated with the datagram. The returned object is a reference
to the byte array that was most recently associated with this DatagramPacket, either
by the constructor or by setData(). The length of the returned buffer may be greater
than the internal datagram length, so the internal length and offset values should be
used to determine the actual received data.
26 Chapter 2: Basic Sockets []
voi d setData(byte[] buffer)
voi d setData(byte[] buffer, int offset, int length)
Makes the given byte array the datagram buffer. The first form makes the entire byte
array the buffer; the second form makes bytes offset through offset + l engt h- 1 the
buffer. The first form never updates the internal offset and only updates the internal
length if the given buffer' s length is less than the current internal length. The second
form always updates the internal offset and length.
buffer Preallocated byte array for datagram packet data
offset Location in buffer where first byte is to be accessed
length Number of bytes to be read from/written into buffer
2.3.2 UDPClient
A UDP client begins by sending a datagram to a server that is passively waiting to be contacted.
The typical UDP client goes through three steps:
1. Construct an instance of DatagramSocket, optionally specifying the local address and port.
2. Communicate by sending and receiving instances of DatagramPacket using the send() and
recei ve() met hods of DatagramSocket.
3. When finished, deallocate the socket using the close() met hod of DatagramSocket.
Unlike a Socket, a DatagramSocket is not constructed with a specific destination address.
This illustrates one of the major differences between TCP and UDP. A TCP socket is required to
establish a connection with another TCP socket on a specific host and port before any data can
be exchanged, and, thereafter, it only communicates with that socket until it is closed. A UDP
socket, on the other hand, is not required to establish a connection before communication, and
each datagram can be sent to or received from a different destination. (The connect () met hod
of DatagramSocket does allow the specification of the remote address and port, but its use is
optional.)
Our UDP echo client, UDPEchoClientTimeout. java, sends a datagram containing the string
to be echoed and prints whatever it receives back from the server. A UDP echo server simply
repeats each datagram that it receives back to the client. Of course, a UDP client only commu-
nicates with a UDP server. Many systems include a UDP echo server for debugging and testing
purposes.
One consequence of using UDP is that datagrams can be lost. In the case of our echo
protocol, either the echo request from the client or the echo reply from the server may be
lost in the network. Recall that our TCP echo client sends an echo string and then blocks on
read () waiting for a reply. If we try the same strategy with our UDP echo client and the echo
request datagram is lost, our client will block forever on receive (). To avoid this problem, our
client specifies a maximum amount of time to block on receive(), after which it tries again by
resending the echo request datagram. Our echo client performs the following steps:
[] 2.3 UDP Sockets 2 7
1. Send t he echo st ri ng to t he server.
2. Block on r ecei ve( ) for up to t hr ee seconds, st ar t i ng over (up to five t i mes) if t he repl y is
not recei ved bef or e t he t i meout .
3. Ter mi nat e t he client.
UDPEchoClientTimeout.java
O i m p o r t j a v a . n e t . * ;
1 i m p o r t j a v a . i o . * ; / / f o r l O B x c e p t i o n
2
3 p u b l i c c l a s s U D P E c h o C l i e n t T i m e o u t {
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/ / for DatagramSocket, DatagramPacket, and InetAddress
p r i v a t e s t a t i c f i n a l i n t T I M E O U T = 3 0 0 0 ;
p r i v a t e s t a t i c f i n a l i n t M A X T R I B S = 5;
/ / R e s e n d t i m e o u t ( m i l l i s e c o n d s )
/ / M a x i m u m r e t r a n s m i s s i o n s
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s l O E x c e p t i o n {
i f ( ( a r g s . l e n g t h < 2 ) I I ( a r g s . l e n g t h > 3 ) ) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) ' < S e r v e r > < W o r d > [ < P o r t > ] " ) ;
I n e t A d d r e s s s e r v e r A d d r e s s = I n e t A d d r e s s . g e t B y N a m e ( a r g s [ 0 ] ) ; / / S e r v e r a d d r e s s
/ / C o n v e r t t h e a r g u m e n t S t r i n g t o b y t e s u s i n g t h e d e f a u l t e n c o d i n g
b y t e [ ] b y t e s Z o S e n d = a r g s [ l ] . g e t B y t e s ( ) ;
i n t s e r v P o r t = ( a r g s . l e n g t h = = 3 ) ? I n t e g e r . p a r s e l n t ( a r g s [ 2 ] ) 9 7;
DatagramSocket socket = new DatagramSocket() ;
s o c k e t . s e t S o T i m e o u t ( T I M E O U T ) ; / / M a x i m u m r e c e i v e b l o c k i n g t i m e ( m i l l i s e c o n d s )
DatagramPacket sendPacket = new DatagramPacket(bytesToSend,
bytesToSend. length, serverAddress, servPort ) ;
/ / S e n d i n g p a c k e t
D a t a g r a m P a c k e t r e c e i v e P a c k e t = / / R e c e i v i n g p a c k e t
n e w D a t a g r a m P a c k e t ( n e w b y t e [ b y t e s T o S e n d . l e n g t h ] , b y t e s T o S e n d . l e n g t h ) ;
i n t t r i e s = 0; / / P a c k e t s m a y b e l o s t , s o w e h a v e t o k e e p t r y i n g
b o o l e a n r e c e i v e d R e s p o n s e = f a l s e ;
d o {
s o c k e t . s e n d ( s e n d P a c k e t ) ; / / S e n d t h e e c h o s t r i n g
t r y {
s o c k e t . r e c e i v e ( r e c e i v e P a c k e t ) ; / / A t t e m p t e c h o r e p l y r e c e p t i o n
i f ( ! r e c e i v e P a c k e t . g e t A d d r e s s ( ) . e q u a l s ( s e r v e r A d d r e s s ) ) / / C h e c k s o u r c e
t h r o w n e w l O E x c e p t i o n ( " R e c e i v e d p a c k e t f r o m a n u n k n o w n s o u r c e " ) ;
r e c e i v e d R e s p o n s e = t r u e ;
28 Chapter 2: Basic Sockets []
40
41
42
43
44
45
46
47
48
49
50
51
52
53
}
}
} c a t c h ( I n t e r r u p t e d l O E x c e p t i o n e ) { / / W e d i d n o t g e t a n y t h i n g
t r i e s + = I;
S y s t e m . o u t . p r i n t l n ( " T i m e d o u t , " + ( ~ T R I E S - t r i e s ) + " m o r e t r i e s . . . " ) ;
}
} w h i l e ( ( ! r e c e i v e d R e s p o n s e ) & & ( t r i e s < ~ s ;
i f ( r e c e i v e d R e s p o n s e )
S y s t e m . o u t . p r i n t l n ( " R e c e i v e d : " + n e w S t r i n g ( r e c e i v e P a c k e t . g e t D a t a ( ) ) ) ;
e l s e
S y s t e m . o u t . p r i n t l n ( " N o r e s p o n s e - - g i v i n g u p . " ) ;
s o c k e t . c l o s e ( ) ;
UDPEchoClientTimeout.java
1. Appl i cat i on s et up and paramet er parsi ng: lines 0-17
Convert ar gume nt to byt es: line 15
2. UDP s oc ke t creati on: line 19
This instance of DatagramSocket can send dat agrams to any UDP socket. We do not specify
a local address or port so some local address and available port will be selected. We can
explicitly set t hem with the setLocalAddress() and set Local Port () met hods or in the
const ruct or.
3. Set t he s oc ke t t i meout : line 21
The t i meout for a dat agram socket controls the maxi mum amount of time (milliseconds)
a call to r ecei ve( ) will block. Here we set the t i meout to three seconds. Note t hat t i meout s
are not precise: the call may block for more t han the specified time (but not less).
4. Creat e dat agr am to send: lines 23-24
To create a dat agram for sending, we need to specify three things: data, dest i nat i on
address, and dest i nat i on port. For the dest i nat i on address, we may identify the echo
server either by name or IP address. If we specify a name, it is converted to the actual IP
address in the constructor.
5. Creat e dat agr am to recei ve: lines 26-27
To create a dat agram for receiving, we only need to specify a byte array to hold the
dat agr am data. The address and port of the dat agram source will be filled in by recei ve ().
6. Send t he datagram: lines 29-44
Since dat agrams may be lost, we must be prepared to ret ransmi t the dat agram. We loop
sending and at t empt i ng a receive of the echo reply up to five times.
9 Send t he datagram: line 32
send() t ransmi t s the dat agram to the address and port specified in the dat agram.
II 2.3 UDP Sockets 29
9 Handl e dat agr am recept i on: lines 33-43
r ecei ve( ) blocks until it either receives a dat agr am or the timer expires. Timer expi-
ration is indicated by an I n t e r r u p t e d l O E x c e p t i o n . If the timer expires, we i ncrement
the send at t empt count (tries) and start over. After the maxi mum number of tries,
the while loop exits wi t hout receiving a dat agram. If r ecei ve( ) succeeds, we set the
loop flag receivedResponse to true, causing the loop to exit. Since packet s may come
from anywhere, we check the source address of the recieved dat agr am to verify that
it mat ches the address of the specified echo server.
7. Print r ecept i on resul t s: lines 46-49
If we received a dat agram, receivedResponse is true, and we can print the dat agram data.
8. Close t he socket: line 51
We invoke the UDP client using the same paramet ers as used in the TCP client.
DatagramSocket
Constructors
DatagramSocket()
DatagramSocket(int localPort)
DatagramSocket(int localPort, I net Addr ess localAddr)
Const ruct s a UDP socket. Either or bot h the local port and address may be specified.
If the local port is not specified, the socket is bound to any available local port. If the
local address is not specified, one of the local addresses is chosen.
localPort Local port; a localPort of 0 allows the const ruct or to pick any
available port.
localAddr Local address
Operat ors
voi d close()
After closing, dat agrams may no longer be sent or received using this socket.
voi d connect (Inet Address remoteAddr, int remotePort)
Sets the remot e address and port of the socket. At t empt i ng to send dat agrams with
a different address will cause an exception to be thrown. The socket will only receive
dat agrams from the specified port and address. Dat agrams from any other port or
address are ignored. This is strictly a local operat i on because there is no end-to-end
connection. Caveat: A socket that is connect ed to a mul t i cast or broadcast address can
30 Chapter 2: Basic Sockets []
only send datagrams, because a datagram source address is always a unicast address
(see Section 4.3).
remoteAddr Remote address
remotePort Remote port
voi d disconnect()
Removes the remote address and port specification of the socket (see connect()).
voi d receive(DatagramPacket packet)
Places data from the next received message into the given DatagramPacket.
packet Receptacle for received information, including source
address and port as well as message data. (See the
DatagramPacket reference for details of semantics.)
voi d send(DatagramPacket packet)
Sends a datagram from this socket.
packet Specifies the data to send and the destination address and
port. If packet does not specify a destination address, the
DatagramSocket must be "connected" to a remote address
and port (see connect ()).
Accessors/Mutatots
Inet Address g e t l n e t A d d r e s s O
int getPort0
Returns the remote socket address/ port .
Inet Address getLocalAddress0
i nt getLocalPort0
Returns the local socket address/port.
int getReceiveBufferSize0
int getSendBufferSize0
voi d setReceiveBufferSize(int size)
voi d setSendBufferSize(int size)
The DatagramSocket has limits on the maximum datagram size that can be sent /
received through this socket. The receive limit also determines the amount of message
data that can be queued waiting to be returned via receive(). That is, when the amount
of buffered data exceeds the limit, arriving packets are quietly discarded. Setting the
size is only a hint to the underlying implementation. Also, the semantics of the limit
may vary from system to system: it may be a hard limit on some and soft on others.
size Desired limit on packet and/ or queue size (bytes)
II 2.3 UDP Sockets 31
int g e t S o T i m e o u t ( )
voi d s e t S o T i m e o u t ( i n t timeout)
Ret ur ns/ set s the maxi mum amount of time t hat a recei ve () will block for this socket.
If the specified time elapses before dat a is available, an Int errupt edl OExcept i on is
thrown.
timeout The maxi mum amount of time (milliseconds) t hat r ecei ve( )
will block for the socket. A t i meout of 0 indicates t hat a
receive will block until dat a is available.
2.3.3 UDPServer
Like a TCP server, a UDP server' s job is to set up a communi cat i on endpoi nt and passively
wait for the client to initiate the communi cat i on; however, since UDP is connectionless, UDP
communi cat i on is initiated by a dat agr am from the client, wi t hout going t hrough a connect i on
setup as in TCP. The typical UDP server goes t hrough four steps:
1. Const ruct an instance of DatagramSocket, specifying the local port and, optionally, the
local address. The server is now ready to receive dat agrams from any client.
2. Receive an instance of DatagramPacket using the r ecei ve( ) met hod of DatagramSocket.
When r ecei ve( ) returns, the dat agram contains the client' s address so we know where
to send the reply.
3. Communi cat e by sending and receiving DatagramPackets using the send() and r ecei ve( )
met hods of DatagramSocket.
4. When finished, deallocate the socket using the cl ose() met hod of DatagramSocket.
Our next pr ogr am example, UDPEchoServer. java, i mpl ement s the UDP version of the echo
server. The server is very simple: it loops forever, receiving dat agrams and t hen sending the
same dat agrams back to the client. Actually, our server only receives and sends back the first
255 (ECHOMAX) charact ers of the dat agram; any excess is silently di scarded by the socket
i mpl ement at i on (see Section 2.3.4).
U D P Ec h oSe r y e r . j a v a
O import j ava. net . *; / / for DatagramSocket, DatagramPacket, and InetAddress
1 import j ava. i o. *; / / for IOException
2
3 public class UDPEchoServer {
4
5 private st at i c fi nal i nt ECHO~X = 255; / / Maximum size of echo datagram
32 Chapter 2: Basic Sockets I
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s lOF, x c e p t i o n {
i f ( a r g s . l e n g t h != i) / / T e s t f o r c o r r e c t a r g u m e n t l i s t
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < P o r t > " ) ;
i n t s e r v P o r t = I n t e g e r . p a r s e l n t ( a r g s [ O ] ) ;
D a t a g r a m S o c k e t s o c k e t = n e w D a t a g r a m S o c k e t ( s e r v P o r t ) ;
D a t a g r a m P a c k e t p a c k e t = n e w D a t a g r a m P a c k e t ( n e w b y t e [ E C H O M A X ] , E C H O M A X ) ;
f o r ( ; ; ) { / / R u n f o r e v e r , r e c e i v i n g a n d e c h o i n g d a t a g r a m s
s o c k e t . r e c e i v e ( p a c k e t ) ; / / R e c e i v e p a c k e t f r o m c l i e n t
S y s t e m . o u t . p r i n t l n ( " H a n d l i n g c l i e n t a t " +
p a c k e t . g e t A d d r e s s ( ) . g e t H o s t A d d r e s s ( ) + " o n p o r t " + p a c k e t . g e t P o r t ( ) ) ;
s o c k e t . s e n d ( p a c k e t ) ; / / S e n d t h e s a m e p a c k e t b a c k t o c l i e n t
p a c k e t . s e t L e n g t h ( E C H O M A X ) ; / / R e s e t l e n g t h t o a v o i d s h r i n k i n g b u f f e r
}
/ * N O T R E A C H E D * /
U D P Ec h oSe r y e r . j a v a
1. Appl i cat i on set up and paramet er parsing: lines 0- 12
UDPEchoServer t akes a single par amet er , t he local por t of the echo server socket.
2. Create and set up datagram socket: line 14
Unlike our UDP client, a UDP server mus t explicitly set its local por t to a number known
by t he client; ot herwi se, t he client will not know the dest i nat i on por t for its echo r equest
dat agr am. When the server recei ves t he echo dat agr am f r om the client, it can find out t he
client' s addr ess and por t f r om the dat agr am.
3. Create datagram: line 15
UDP messages are cont ai ned in dat agr ams. We const r uct an i nst ance of DatagramPacket
wi t h a buffer of ECHOMAX (255) bytes. This dat agr am will be used bot h to receive t he echo
r equest and to send t he echo reply.
4. Iterati vel y handl e i ncomi ng echo requests: lines 17-23
The UDP server uses a single socket for all communi cat i on, unl i ke t he TCP server, whi ch
creat es a new socket wi t h every successful accept ().
9 Recei ve an echo request datagram: lines 18- 20
The r ecei ve( ) met hod of DatagramSocket bl ocks unt i l a dat agr am is recei ved f r om a
client (unl ess a t i meout is set). There is no connect i on, so each dat agr am may come
[] 2.3 UDP Sockets ~
from a different sender. The dat agram itself contains the sender' s (client's) source
address and port.
9 Send echo reply: line 21
packet already contains the echo string and echo reply dest i nat i on address and port,
so the send() met hod of DatagramSocket can simply t ransmi t the dat agr am previously
received. Note that when we receive the datagram, we i nt erpret the dat agram address
and port as the source address and port, and when we send a dat agram, we i nt erpret
the dat agram' s address and port as the destination address and port.
9 Reset buffer size: line 22
The internal length of packet was set to the length of the message j ust processed,
which may have been smaller t han the original buffer size. If we do not reset the
internal length before receiving again, the next message will be t runcat ed if it is longer
t han the one j ust received.
2.3.4 Sending and Receiving with UDP Sockets
A subtle but i mport ant difference bet ween TCP and UDP is that UDP preserves message
boundaries. Each call to r ecei ve( ) ret urns data from at most one call to send() Moreover,
different calls to r ecei ve( ) will never ret urn dat a from the same call to send().
When a call to wr i t e( ) on a TCP socket' s out put st ream returns, all the caller knows is
that the data has been copied into a buffer for t ransmi ssi on; the data may or may not have
actually been t r ansmi t t ed yet. (This is covered in more detail in Chapter 5.) UDP, however, does
not provide recovery from net work errors and, therefore, does not buffer data for possible
ret ransmi ssi on. This means that by the time a call to send() returns, the message has been
passed to the underl yi ng channel for t ransmi ssi on and is (or soon will be) on its way out the
door.
Between the time a message arrives from the net work and the time its data is ret urned via
read() or r ecei ve( ) , the data is st ored in a first-in, first-out (FIFO) queue of received data. With
a connect ed TCP socket, all received-but-not-yet-delivered bytes are t reat ed as one cont i nuous
sequence of bytes (see Chapter 5). For a UDP socket, however, the received dat a may have come
from different senders. A UDP socket' s received data is kept in a queue of messages, each with
associ at ed i nformat i on identifying its source. A call to r ecei ve( ) will never ret urn more t han
one message. However, if r ecei ve( ) is called with a DatagramPacket containing a buffer of size
n, and the size of the first message in the receive queue exceeds n, only the first n bytes of
the message are ret urned. The remai ni ng bytes are quietly discarded, with no indication to the
receiving pr ogr am t hat i nformat i on has been lost!
For this reason, a receiver shoul d always supply a DatagramPacket with a buffer big enough
to hold the largest message allowed by its application protocol at the time it calls r ecei ve( ) .
This technique will guarant ee that no data will be lost. The maxi mum amount of data that can
be t ransmi t t ed in a DatagramPacket is 65,507 byt es- - t he largest payload that can be carried in
a UDP dat agram. It is i mport ant to r emember here that each instance of DatagramPacket has an
internal not i on of message length that may be changed whenever a message is received into
34 Chapter 2: Basic Sockets []
that instance (to reflect the number of bytes in the received message). Applications that call
recei ve() more than once with the same instance of DatagramPacket should explicitly reset the
internal length to the actual buffer length before each subsequent call to recei ve().
Another potential source of problems for beginners is the getData() met hod of Data-
gramPacket, which always returns the entire original buffer, ignoring the internal offset and
length values. Receiving a message into the DatagramPacket only modifies those locations of
the buffer into which message data was placed. For example, suppose buf is a byte array of
size 20, which has been initialized so that each byte contains its index in the array:
0 ] 1 I 2 I 3 I 4 I 510 1 ~ I ~ I 9 I 10 111112113114 115116117118119 I
Suppose also that dg is a DatagramPacket, and that we set dg's buffer to be the middle 10 bytes
of buf :
dg. setData(buf, 5,10) ;
Now suppose that dgsocket is a DatagramSocket, and that somebody sends an 8-byte message
containing
I 41 I 42 143 I 44 I 45 I 46 I 47148 I
to dgsocket. The message is received into dg:
dgsocket .receive(dg) ;
Now, calling dg. getData() returns a reference to the original byte array buf, whose contents
are now
0 I 11 2 I 3 I 4 I 411 421 431 441 451 461 471 481 131 141 151 161 171 181 19 I
Note that only bytes 5-12 of buf have been modified and that, in general, the application
needs to use get 0f f set ( ) and getData() to access just the received data. One possibility is to
copy the received data into a separate byte array, like this:
byte[] destBuf = new byte[dg.getLength()];
System.arraycopy(dg.getData(), dg.getOffset(), destSuf, O, destSuf.length);
2. 4 Exerci ses
1. For TCPF.choServer. java, we explicitly specify the port to the socket in the constructor.
We said that a socket must have a port for communication, yet we do not specify a port
in TCPY.choClient. java. How is the echo client' s socket assigned a port?
2. When you make a phone call, it is usually the callee that answers with "Hello." What
changes to our client and server examples would be needed to i mpl ement this?
3. What happens if a TCP server never calls accept()? What happens if a TCP client sends
data on a socket that has not yet been accept ()ed at the server?
[] 2.4 Exercises ~
4. Servers are supposed to run for a long time wi t hout st oppi ng--t herefore, they must be
desi gned to provide good service no mat t er what their clients do. Examine the server
examples (TCPEchoServer. java and UDPEchoServer. java) and list anyt hi ng you can think
of t hat a client mi ght do to cause it to give poor service to other clients. Suggest
i mprovement s to fix the probl ems t hat you find.
5. Modify TCPEchoServer. java to read and write only a single byte at a time, sleeping one
second bet ween each byte. Verify t hat TCPEchoClient.java requires multiple reads to
successfully receive the entire echo string, even t hough it sent the echo string with one
wri t e().
6. Modify TCPEchoServer. java to read and write a single byte and t hen close the socket.
What happens when the TCPEchoClient sends a mul t i byt e string to this server? What is
happening? (Note t hat the response could vary by OS.)
7. Modify UDPEchoServer. java so t hat it only echoes every other dat agr am it receives. Verify
t hat UDPEchoClientTimeout. java ret ransmi t s dat agrams until it either receives a reply or
exceeds the number of retries.
8. Modify UDPEchoServer. java so t hat ECHOMAX is much short er (say, 5 bytes). Then use
UDPEchoClientTimeout. java to send an echo string t hat is too long. What happens?
9. Verify experi ment al l y the size of the largest message you can send and receive using a
DatagramPacket.
10. While UDPEchoServer. java explicitly specifies its local port in the const ruct or, we do not
specify the local port in UDPEchoClientTimeout. java. How is the UDP echo client' s socket
given a port number? Hint: The answer is different for TCP.
chapt er 3
Sending and Receiving Messages
Wh e n wri t i ng pr ogr ams to communi cat e via sockets, you will general l y be i mpl ement i ng
an application protocol of some sort. Typically you use socket s because your pr ogr am needs to
provi de i nf or mat i on to, or use i nf or mat i on provi ded by, anot her program. There is no magic:
sender and receiver mus t agree on how this i nf or mat i on will be encoded, who sends what
i nf or mat i on when, and how the communi cat i on will be t ermi nat ed. In our echo exampl e, the
appl i cat i on prot ocol is trivial: nei t her the client' s nor the server' s behavi or is affect ed by the
contents of the byt es t hey exchange. Because most appl i cat i ons requi re t hat the behavi ors of
client and server depend upon the information t hey exchange, appl i cat i on prot ocol s are usual l y
more compl i cat ed.
The TCP/IP prot ocol s t r anspor t byt es of user dat a wi t hout exami ni ng or modi fyi ng t hem.
This allows appl i cat i ons great flexibility in how t hey encode their i nf or mat i on for t ransmi ssi on.
For vari ous reasons, most appl i cat i on prot ocol s are defi ned in t er ms of di scret e messages
made up of sequences of fields. Each field cont ai ns a specific piece of i nf or mat i on encoded
as a sequence of bits. The appl i cat i on prot ocol specifies exactly how t hese sequences of bits
are to be f or mat t ed by the sender and i nt erpret ed, or parsed, by the receiver so t hat the l at t er
can ext ract the meani ng of each field. About the only const r ai nt i mposed by TCP/IP is t hat
i nf or mat i on mus t be sent and recei ved in chunks whose l engt h in bi t s is a mul t i pl e of eight. So
f r om now on we consi der messages to be sequences of bytes. Given this, it may be hel pful to
t hi nk of a t r ansmi t t ed message as a sequence of number s, each bet ween 0 and 255, inclusive
(that bei ng the range of bi nary values t hat can be encoded in 8 bi t s- - 1 byte).
As a concret e exampl e for this chapt er, let' s consi der the pr obl em of t ransferri ng price
quot e i nf or mat i on bet ween vendor s and buyers. A si mpl e quot e for some quant i t y of a
part i cul ar i t em mi ght include the following i nformat i on:
I t em number : A large i nt eger i dent i fyi ng the i t em
I t em descr i pt i on: A t ext st ri ng descri bi ng the i t em
Unit pri ce: The cost per i t em in cent s
Quant i t y: The number of uni t s offered at t hat price
37
38 Chapter 3" Sending and Receiving Messages u
Di s c ount e d?: Whet her t he pri ce i ncl udes a di scount
In st ock?: Whet her t he i t em is in st ock
We col l ect t hi s i nf or mat i on in a cl ass ItemQuote. java. For conveni ence in vi ewi ng t he i nf or ma-
t i on in our pr ogr a m exampl es, we i ncl ude a t oSt r i ng( ) met hod. Thr oughout t hi s chapt er , t he
vari abl e i t em r ef er s to an i nst ance of ItemQuote.
ItemQuote.java
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
0 p u b l i c c l a s s I t e m Q u o t e {
p u b l i c l o n g i t e m N u m b e r ; / / I t e m i d e n t i f i c a t i o n n u m b e r
p u b l i c S t r i n g i t e m D e s c r i p t i o n ; / / S t r i n g d e s c r i p t i o n o f i t e m
p u b l i c i n t q u a n t i t y ; / / N u m b e r o f i t e m s i n q u o t e ( a l w a y s > = i)
p u b l i c i n t u n i t P r i c e ; / / P r i c e ( i n c e n t s ) p e r i t e m
p u b l i c b o o l e a n d i s c o u n t e d ; / / P r i c e r e f l e c t a d i s c o u n t ?
p u b l i c b o o l e a n i n S t o c k ; / / I t e m ( s ) r e a d y t o s h i p ?
p u b l i c I t e m Q u o t e ( l o n g i t e m N u m b e r , S t r i n g i t e m D e s c r i p t i o n ,
i n t q u a n t i t y , i n t u n i t P r i c e , b o o l e a n d i s c o u n t e d , b o o l e a n i n S t o c k )
t h i s i t e m N u m b e r = i t e m N u m b e r ;
t h i s i t e m D e s c r i p t i o n = i t e m D e s c r i p t i o n ;
t h i s q u a n t i t y = q u a n t i t y ;
t h i s u n i t P r i c e = u n i t P r i c e ;
t h i s d i s c o u n t e d = d i s c o u n t e d ;
t h i s i n S t o c k = i n S t o c k ;
p u b l i c S t r i n g t o S t r i n g ( ) {
f i n a l S t r i n g E O L N = j a v a . l a n g . S y s t e m . g e t P r o p e r t y ( " l i n e . s e p a r a t o r " ) ;
S t r i n g v a l u e = " I t e m # = " + i t e m N u m b e r + E O L N +
" D e s c r i p t i o n = " + i t e m D e s c r i p t i o n + E O L N +
" Q u a n t i t y = " + q u a n t i t y + B O L N +
" P r i c e ( e a c h ) = " + u n i t P r i c e + B O L N +
" T o t a l = " + ( q u a n t i t y * u n i t P r i c e ) ;
i f ( d i s c o u n t e d )
v a l u e + = " ( d i s c o u n t e d ) " ;
i f ( i n S t o c k )
v a l u e + = B O L N + " I n S t o c k " + E O L N ;
e l s e
v a l u e + = E O L N + " O u t o f S t o c k " + E O L N ;
r et ur n v a l u e ;
ItemQuote.java
[] 3.1 Encoding Information 39
3.1 Encoding I nformat i on
What if a client pr ogr am needs to obt ai n quot e i nf or mat i on f r om a vendor program? The two
pr ogr ams mus t agree on how the i nf or mat i on cont ai ned in the ItemQuote will be r epr esent ed
as a sequence of byt es "on the wi r e"- - sent over a TCP connect i on or carri ed in a UDP dat agram.
(Note t hat everyt hi ng in this chapt er also applies if the "wire" is a file t hat is wr i t t en by one
pr ogr am and read by another. ) In our example, the i nf or mat i on to be r epr esent ed consi st s of
pri mi t i ve t ypes (integers, bool eans) and a charact er string.
Tr ansmi t t i ng i nf or mat i on via the net wor k in Java requi res t hat it be wr i t t en to an Out-
putStream (of a Socket) or encapsul at ed in a DatagramPacket (which is t hen sent via a Data-
gramSocket). However, the only dat a t ypes to whi ch t hese operat i ons can be appl i ed are byt es
and arrays of byt es. As a st rongl y t yped language, Java requi res t hat ot her t ypes- - St r i ng, int,
and so on- - be explicitly convert ed to t hese t r ansmi t t abl e types. Fort unat el y, the l anguage has
a number of built-in facilities t hat make such conversi ons more convenient. Before dealing
wi t h the specifics of our exampl e, however, we focus on some basic concept s of r epr esent i ng
i nf or mat i on as sequences of byt es for t ransmi ssi on.
3.1.1 Text
Ol d-fashi oned t ext - - st r i ngs of pri nt abl e (displayable) char act er s- - i s per haps the most com-
mon f or m of i nf or mat i on represent at i on. When the i nf or mat i on to be t r ansmi t t ed is nat ur al
language, text is the most nat ur al represent at i on. Text is conveni ent for ot her forms of in-
f or mat i on because humans can easily deal wi t h it when pr i nt ed or displayed; number s, for
example, can be r epr esent ed as st ri ngs of deci mal digits.
To send text, the st ri ng of charact ers is t r ansl at ed into a sequence of byt es accordi ng
to a character set. The canonical exampl e of a charact er encodi ng syst em is the venerabl e
American Standard Code for Information Interchange (ASCII), whi ch defines a one-to-one
mappi ng bet ween a set of the most commonl y used pri nt abl e charact ers in English, and bi nary
values. For exampl e, in ASCII the digit 0 is r epr esent ed by the byt e value 48, 1 by 49, and so
on up to 9, whi ch is r epr esent ed by the byt e value 57. ASCII is adequat e for appl i cat i ons t hat
only need to exchange English text. As the economy becomes i ncreasi ngl y globalized, however,
appl i cat i ons need to deal wi t h ot her l anguages, i ncl udi ng many t hat use charact ers for whi ch
ASCII has no encoding, and even some (e.g., Chinese) t hat use mor e t han 256 charact ers and
t hus requi re mor e t han I byt e per charact er to encode. Encodings for the worl d' s l anguages are
defined by compani es and by st andar ds bodies. Unicode is the most widely r ecogni zed such
charact er encoding; it is st andar di zed by the Int ernat i onal Organi zat i on for St andar di zat i on
(ISO).
Fort unat el y, Java provi des good suppor t for i nt ernat i onal i zat i on, in several ways. First,
Java uses Unicode to r epr esent charact ers internally. Unicode defines a 16-bit (2-byte) code
for each charact er and t hus suppor t s a much larger set of charact ers t han ASCII. In fact, the
Unicode st andar d current l y defines codes for over 49, 000 charact ers and covers "the pri nci pal
wri t t en l anguages and symbol syst ems of the world." [21] Second, Java suppor t s vari ous ot her
st andar d encodi ngs and provi des a clean separ at i on bet ween its i nt ernal r epr esent at i on and
the encodi ng used when charact ers are i nput or out put .
~O Chapter 3: Sending and Receiving Messages n
The getBytes() met hods of class St ri ng implement this internal-to-external conversion,
ret urni ng the sequence of bytes that represent the given string in some ext ernal encodi ng--
either the default encoding or an explicitly named one. (This type of conversion may also
happen implicitly--for example, by writing a string to an instance of 0utputStreamWriter.)
Similarly, St ri ng provides const ruct ors that take a byte array and the name of a particular
encoding, and ret urn a St ri ng instance containing the sequence of characters represent ed by
the byte sequence according to the encoding. (If no encoding is explicitly requested, the default
encoding for the pl at form is used.)
Suppose the value of i t em. i t emNumber is 123456. Using ASCII, that part of the string
represent at i on of i t em produced by t oSt r i ng( ) would be encoded as
1 1 0 5 1 1 1 6 1 1 0 1 1 1 0 9 L 1 6 1 1 4 9 1 5 0 1 5 1 1 2 1 31 4 I
' i ' ' t ' ' e ' ' m ' ' # ' ' = ' ' i ' ' 2 ' ' 3 ' ' 4 ' ' 5 ' ' 6 '
Using the "ISO8859_1" encoding would produce the same sequence of byte values, because the
Int ernat i onal St andard 8859-1 encoding (which is also known as ISO Latin 1) is an extension
of ASCII--it maps the characters of the ASCII set to the same values as ASCII. However, if we
used the North American version of IBM's Ext ended Bi nary Coded Deci mal Int erchange Code
(EBCDIC), known in Java as the encoding "Cp037," the result would be rather different:
1 1 371 1 6 3L 1 331 1 4 81 1 2 31 1 2 6 1 2 4 1 1 2 4 2 1 2 4 31 2 4 4 1 2 4 1 2 4 6 1
' i ' ' t ' ' e' 'm' ' #' ' =' ' 1' ' 2' ' 3' ' 4' ' 5' ' 6'
If we used Unicode, the result would use 2 bytes per character, with i byte containing zero and
the other byte containing the same value as with ASCII. Obviously the pri mary requi rement in
dealing with character encodings is that the sender and receiver must agree on the code to be
used.
3.1.2 Binary Numbers
Transmi t t i ng large numbers as text strings is not very efficient: each character in the digit string
has one of only 10 values, which can be represent ed using, on average, less t han 4 bits per
digit. Yet the st andard character codes invariably use at least 8 bits per character. Moreover, it
is inconvenient to perform arithmetic comput at i on and compari sons with numbers encoded
as strings. For example, a receiving program comput i ng the total cost of a quote (quantity
times unit price) will generally need to convert bot h amount s to the local comput er' s native
(binary) integer represent at i on before the comput at i on can be performed. For a more compact
and computation-friendly encoding, we can t ransmi t the values of the integers in our data as
binary values. To send binary integers as byte sequences, the sender and receiver need to agree
on several things:
9 Int eger size: How many bits are used to represent the integer? The sizes of Java' s integer
types are fixed by the language defi ni t i on--short s are 2 bytes, ints are 4, longs are
8--so a Java sender and receiver only need to agree on the primitive type to be used.
(Communicating with a non-Java application may be more complex.) The size of an integer
i 3.1 Encoding Information ~ |
type, along wi t h the encodi ng (si gned/ unsi gned, see below), det er mi nes the maxi mum
and mi ni mum values t hat can be r epr esent ed usi ng t hat type.
9 Byte order: Are the byt es of the bi nary r epr esent at i on wr i t t en to the st r eam (or pl aced in
the byt e array) f r om left to ri ght or ri ght to left? If the most significant byt e is t r ansmi t t ed
first and the l east significant byt e is t r ansmi t t ed last, t hat ' s the so-called bi g-endi an order.
Little-endian is, of course, j ust the opposi t e.
9 Signed or unsigned: Signed i nt egers are usual l y t r ansmi t t ed in t wo' s-compl ement repre-
sent at i on. For k-bit number s, the t wo' s- compl ement encodi ng of the negat i ve i nt eger - n ,
1 < n < 2 k- l , is the bi nary value of 2 k - n; and the non-negat i ve i nt eger p, 0 < p < 2 k-1 - 1,
is encoded si mpl y by the k-bit bi nary value of p. Thus, given k bits, t wo' s compl ement can
r epr esent val ues in the range - 2 k-1 t hr ough 2 k-1 - 1, and the most significant bit (msb)
tells whet her the value is positive (msb = 0) or negat i ve (msb = 1). On the ot her hand, a
k-bit unsi gned i nt eger can encode values in the range 0 t hr ough 2 k - 1 directly.
Consi der again the i t emNumber. It is a long, so its bi nary r epr esent at i on is 64 bi t s (8
bytes). If its value is 12345654321 and the encodi ng is big-endian, the 8 byt es sent woul d be
(with t he byt e on the left t r ansmi t t ed first):
0 0 0 2 223 219 188 49
If, on the ot her hand, the value was sent in l i t t l e-endi an order, the t r ansmi t t ed byt e values
woul d be:
If the sender uses bi g-endi an when the receiver is expect i ng little-endian, the receiver will end
up wi t h an i t emNumber of 3583981154337816576! Most net wor k prot ocol s specify bi g-endi an
byt e order; in fact it is somet i mes called net work byte order.
Note t hat the most significant bit of the 64-bit bi nary value of 12345654321 is O, so its
si gned (t wo' s-compl ement ) and unsi gned r epr esent at i ons are the same. More generally, the
di st i nct i on bet ween k-bit si gned and unsi gned values is i rrel evant for val ues t hat lie in the
range 0 t hr ough 2 k-1 - 1. Unfort unat el y, prot ocol s oft en use unsi gned integers; Java' s lack of
unsi gned i nt eger t ypes means t hat some care is requi red in dealing wi t h such values, especially
in decoding. (See pr ogr am ItemQuoteDecoderBin. java in Section 3.4.2 for an example.)
As wi t h strings, Java provi des mechani sms to t ur n pri mi t i ve i nt eger t ypes into sequences
of byt es and vice versa. In part i cul ar, st r eams t hat suppor t the Data0utput i nt erface have
met hods wr i t eShor t (), wr i t eI nt (), and writeLong(), whi ch allow t hose t ypes to be wr i t t en
out directly. These met hods all write out the byt es of i nt eger pri mi t i ve t ypes in bi g-endi an byt e
order usi ng t wo' s- compl ement r epr esent at i on. Similarly, i mpl ement at i ons of the DataInput
i nt erface have met hods r eadI nt ( ) , r eadShor t ( ) , and so on. The next sect i on descri bes some
ways to compose i nst ances of t hese classes.
2 Chapter 3: Sending and Receiving Messages []
DataOutputStream BufferedOutputStream
w r i t e D o u b l e ( 3 . 1 4 ) - ' - - ~ 1 ~ - I 3 . 1 4 ( 8 b y t e s ) ~ 3 . 1 4
3 4 3 ( 4 b y t e s ) ~ 3 4 3
writelnt(343) < , I 800 (2 bytes) ~ 800 I
w r i t e S h o r t ( 8 0 0 ) --~
DatalnputStream BufferedlnputStream
readDouble ()=readlnt ( ) I I ~ I ~
~____1 3.14 (8 bytes) ~= I ~ 3.14
343 (4 bytes) ~ 343 i =
[ Z soo
readShort() = I 800 (2 bytes) = I
!
F i g u r e 3. 1 : Stream composition.
OutputStream
L
InputStream
I
3.2 Composi ng I / 0 Streams
Java' s st ream classes can be composed to provide powerful encoding and decoding facilities.
For example, we can wrap the 0utputStream of a Socket instance in a Buffered0utputStream
instance to improve performance by buffering bytes temporarily and flushing t hem to the
underlying channel all at once. We can t hen wrap that instance in a Data0utputStream to send
primitive data types. We would code this composi t i on as follows:
S o c k e t s o c k e t = n e w S o c k e t ( s e r v e r , p o r t ) ;
D a t a O u t p u t S t r e a m out = n e w D a t a O u t p u t S t r e a m (
n e w B u f f e r e d O u t p u t S t r e a m ( s o c k e t . g e t O u t p u t S t r e a m ( ) ) ) ;
Figure 3.1 demonst rat es this composition. Here, we write our primitive data values, one by
one, to Data0utputStream, which writes the binary data to Buffered0utputStream, which buffers
the data from the three writes and t hen writes once to the socket 0utputStream, which controls
writing to the network. We create a parallel composi t i on for the InputStream on the other
endpoi nt to efficiently receive primitive data types.
A complete description of the Java I/O API is beyond the scope of this text; however, Table
3.1 provides a list of some of the relevant Java I/O classes as a starting point for exploiting its
capabilities.
3.3 Framing and Parsing
Converting data to wire format is of course only half the story; the original i nformat i on must
be recovered at the receiver from the t ransmi t t ed sequence of bytes. Application protocols
typically deal with discrete messages, which are viewed as collections of fields. Framing refers
to the probl em of enabling the receiver to locate the beginning and end of the message in
m 3.3 Framing and Parsing 4 3
I/O Class Function
Buffered[ I nput/Output ]Stream
Checked[ I nput/Output ]Stream
Data[ I nput/Output]Stream
Digest[ I nput/Output]Stream
GZI P[ I nput/Output]Stream
Object[ I nput/Output ]Stream
PushbackI nputStream
PrintOutputStream
ZI P[ I nput/Output]Stream
Performs bufferi ng for I/O opt i mi zat i on.
Maintains a checksum on data.
Handles read/ wri t e for primitive dat a types.
Maintains a digest on data.
De/ compr esses a byte st ream in GZIP format.
Handles read/ wri t e objects and primitive dat a types.
Allows a byte or byt es to be "unread."
Prints string r epr esent at i on of dat a type.
De/ compr esses a byte st ream in ZIP format.
Table 3.1 : Java I/O Classes
t he st r eam, and of t he fields wi t hi n t he message. Whet her i nf or mat i on is encoded as text, as
mul t i byt e bi nar y number s , or as some combi nat i on of t he two, t he appl i cat i on pr ot ocol mus t
enabl e t he recei ver of a mes s age to det er mi ne whe n it has r ecei ved all of t he mes s age and to
par se it i nt o fields.
If t he fields in a mes s age all have fixed si zes and t he mes s age is made up of a fixed
numbe r of fields, t hen t he si ze of t he mes s age is known in advance and t he recei ver can
si mpl y r ead t he expect ed numbe r of byt es i nt o a byt e[ ] buffer. Thi s t echni que was us e d in
TCPEchoClient. java, wher e we knew t he numbe r of byt es to expect f r om t he server. However,
when some field ( and/ or t he whol e message) can vary in l engt h, as wi t h t he itemDescription in
our exampl e, we do not know be f or e ha nd how ma ny byt es to read.
Marki ng t he end of t he mes s age is easy in t he speci al case of t he l ast mes s age to be
sent on a TCP connect i on: t he s ender si mpl y cl oses t he sendi ng si de of t he connect i on (usi ng
shut down0ut put () or cl os e( ) ) af t er sendi ng t he message. Aft er t he recei ver r eads t he l ast byt e
of t he message, it recei ves an end- of - s t r eam i ndi cat i on (i.e., r ead( ) r et ur ns -1), and t hus can
tell t hat it has as muc h of t he mes s age as t her e will ever be. The same pr i nci pl e appl i es to t he
l ast field in a mes s age sent as a DatagramPacket.
In all ot her cases, t he mes s age i t sel f mus t cont ai n addi t i onal f r ami ng i nf or mat i on en-
abl i ng t he recei ver to par s e t he f i el d/ message. Thi s i nf or mat i on t ypi cal l y t akes one of t he
fol l owi ng forms:
9 Delimiter: The end of t he var i abl e- l engt h field or mes s age is i ndi cat ed by a uni que marker,
an explicit byt e s equence t hat i mmedi at el y fol l ows, but does not occur in, t he dat a.
9 Explicit length: The var i abl e- l engt h field or mes s age is pr e c e de d by a (fixed-size) l engt h
field t hat tells how ma ny byt es it cont ai ns.
The del i mi t er - based a ppr oa c h is of t en us e d wi t h var i abl e- l engt h text: A par t i cul ar char-
act er or s equence of char act er s is def i ned to ma r k t he end of t he field. If t he ent i re mes s age
consi st s of text, it is s t r ai ght f or war d to r ead in char act er s usi ng an i nst ance of Reader (whi ch
44 Chapter 3: Sending and Receiving Messages []
handles the byte-to-character translation), looking for the delimiter sequence, and ret urni ng
the character string preceding it.
Unfortunately, the Reader classes do not support reading binary data. Moreover, the
relationship between the number of bytes read from the underlying InputStream and the
number of characters read from the Reader is unspecified, especially with multibyte encodings.
When a message uses a combination of the two framing met hods ment i oned above, with some
explicit-length-delimited fields and others using character markers, this can create problems.
The class Framer, defined below, allows an InputStream to be parsed as a sequence of
fields delimited by specific byte patterns. The static met hod Framer.nextToken() reads bytes
from the given InputStream until it encounters the given sequence of bytes or the st ream ends.
All bytes read up to that point are then ret urned in a new byte array. If the end of the st ream is
encount ered before any data is read, nul l is returned. The delimiter can be different for each
call to nextToken(), and the met hod is completely i ndependent of any encoding.
A couple of words of caution are in order here. First, nextToken() is terribly inefficient;
for real applications, a more efficient pattern-matching algorithm should be used. Second,
when using Framer.nextToken() with text-based message formats, the caller must convert the
delimiter from a character string to a byte array and the ret urned byte array to a character
string. In this case the character encoding needs to distribute over concatenation, so that it
doesn' t mat t er whet her a string is converted to bytes all at once, or a little bit at a time.
To make this precise, let E() represent an encodi ng--t hat is, a function that maps
character sequences to byte sequences. Let a and b be sequences of characters, so E(a)
denot es the sequence of bytes that is the result of encoding a. Let "+" denote concatenation
of sequences, so a + b is the sequence consisting of a followed by b. This explicit-conversion
approach (as opposed to parsing the message as a character stream) should only be used with
encodings that have the propert y that E(a + b)= E(a)+ E(b); otherwise, the results may be
unexpected. Although most encodings support ed in Java have this property, some do not.
In particular, UnicodeBig and UnicodeLittle encode a St ri ng by first out put t i ng a byte-order
indicator (the 2-byte sequence 254-255 for big-endian, and 255-254 for little-endian), followed
by the 16-bit Unicode value of each character in the String, in the indicated byte order. Thus,
the encoding of "Big fox" using UnicodeBig is as follows:
1 2 4 1 2 5 1 0 1 6 6 I o 1 1 0 5 1 0 1 1 0 31 0 1 32 1 0 1 1 0 2 1 0 I i1 1 1 0 1 1 2 0 1
[ m a r k ] ' B ' ' i ' ' g ' ' ' ' f ' ' o ' ' x '
while the encoding of "Big" concatenated with the encoding of "fox", using the same encoding,
is as follows"
1 2 4 J 2 1 o 1 6 6 I o j l0 5 1 0 1 1 o31 2 4 1 2 5 1 0 1 32 I o 1 1 o2 1 o i X lll 0 1 1 2 ol
[ m a r k ] ' B ' ' i ' ' g ' [ m a r k ] ' ' ' f ' ' o ' ' x '
Using either of these encodings to convert the delimiter results in a byte sequence that
begins with the byte-order marker. Moreover, if the byte array ret urned by nextToken() does not
begin with one of the markers, any at t empt to convert it to a St ri ng using one of these encodings
[] 3.3 Framing and Parsing 4
will t hrow an exception. The encodi ngs Uni codeBi gUnmarked and Uni codeLi t t l eUnmarked
(support ed in JDK as of 1.3) omi t the byt e-order marker, so t hey are suitable for use wi t h
Framer. nextToken().
Framerjava
0 i m p o r t j a v a . i o . * ;
1
2 p u b l i c c l a s s F r a m e r {
3
4
5
6
7
8
9
i 0
I i
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 2
2 3
2 4 }
2 5
2 6
2 7
2 8
2 9
3 0
3 1
3 2
3 3
3 4
3 5 }
3 6 }
/ / f o r I n p u t S t r e a m a n d B y t e A r r a y O u t p u t S t r e a m
p u b l i c s t a t i c b y t e [ ] n e x t T o k e n ( I n p u t S t r e a m in, b y t e [ ] d e l i m i t e r )
t h r o w s l O E x c e p t i o n {
i n t n e x t B y t e ;
/ / I f t h e s t r e a m h a s a l r e a d y e n d e d , r e t u r n n u l l
i f ( ( n e x t B y t e = i n . r e a d ( ) ) = = - i )
r e t u r n n u l l ;
B y t e A r r a y O u t p u t S t r e a m t o k e n B u f f e r = n e w B y t e A r r a y O u t p u t S t r e a m ( ) ;
d o {
t o k e n B u f f e r . w r i t e ( n e x t B y t e ) ;
b y t e [ ] c u r r e n t T o k e n = t o k e n B u f f e r . t o B y t e A r r a y ( ) ;
i f ( e n d s W i t h ( c u r r e n t T o k e n , d e l i m i t e r ) ) {
i n t t o k e n L e n g t h = c u r r e n t T o k e n . l e n g t h - d e l i m i t e r . l e n g t h ;
b y t e [ ] t o k e n = n e w b y t e [ t o k e n L e n g t h ] ;
S y s t e m . a r r a y c o p y ( c u r r e n t T o k e n , O, t o k e n , O, t o k e n L e n g t h ) ;
r e t u r n t o k e n ;
}
} w h i l e ( ( n e x t B y t e = i n . r e a d ( ) ) != - i ) ; / / S t o p o n e n d - o f - s t r e a m
r e t u r n t o k e n B u f f e r . t o B y t e A r r a y ( ) ; / / R e c e i v e d a t l e a s t 1 b y t e
/ / R e t u r n s t r u e i f v a l u e e n d s w i t h t h e b y t e s i n s u f f i x
p r i v a t e s t a t i c b o o l e a n e n d s W i t h ( b y t e [ ] v a l u e , b y t e [ ] s u f f i x ) {
i f ( v a l u e . l e n g t h < s u f f i x . l e n g t h )
r e t u r n f a l s e ;
f o r ( i n t o f f s e t = i; o f f s e t < = s u f f i x . l e n g t h ; o f f s e t + + )
i f ( v a l u e [ v a l u e . l e n g t h - o f f s e t ] != s u f f i x [ s u f f i x . l e n g t h - o f f s e t ] )
r e t u r n f a l s e ;
r e t u r n t r u e ;
Framerjava
46 Chapter 3: Sending and Receiving Messages !
1. next Token(): l i nes 4- 24
Read f r om i nput s t r eam unt i l del i mi t er or end- of - st r eam.
9 Tes t f or end- of - s t r eam: l i nes 8- 10
If t he i nput s t r eam is al r eady at end- of - st r eam, r e t ur n nul l .
9 Cr eat e a buf f er t o hol d t he byt e s of t he t oken: line 12
We use a Byt eArray0ut put St ream to col l ect t he dat a byt e by byt e. The Byt eAr r ay[ I nput I
Output ]St ream cl asses allow a byt e ar r ay to be handl ed like a s t r eam of byt es.
9 Put t he l ast byt e r e a d i nt o t he buf f er 9 line 14
9 Get a byt e a r r a y c ont a i ni ng t he i nput so far: line 15
It is very i neffi ci ent to cr eat e a new byt e ar r ay on each i t erat i on, but it is si mpl e.
9 Che c k wh e t h e r t he del i mi t er is a suffi x of t he c ur r e nt t oken: l i nes 16-21
If so, cr eat e a new byt e ar r ay cont ai ni ng t he byt es r ead so far, mi nus t he del i mi t er
suffix, and r et ur n it.
9 Get next byt e: line 22
9 Re t ur n t he c ur r e nt t o k e n on end- of - s t r eam: line 23
2. endswi t h( ) : l i nes 26- 35
9 Compa r e l engt hs : l i nes 28- 29
The candi dat e s equence mus t be at l east as l ong as t he del i mi t er to be a mat ch.
9 Compa r e byt es , r e t u r n f a l s e on a ny di f f er ence: l i nes 31- 33
Compar e t he l ast delim.length byt es of t he t oken to t he del i mi t er.
9 If no di f f er ence, r e t u r n t r ue: line 34
3. 4 I mpl e me nt i ng Wi re For mat s in Java
To e mpha s i z e t he fact t hat t he same i nf or mat i on can be r e pr e s e nt e d "on t he wire" in di f f er ent
ways, we defi ne an i nt er f ace ItemQuoteEncoder, whi ch has a single me t hod t hat t akes an
ItemQuote i nst ance and conver t s it to a byt e[ ] t hat can be wr i t t en to an 0ut put St r eam or
encaps ul at ed in a DatagramPacket.
ItemQuoteEncoder.java
0 p u b l i c i n t e r f a c e I t e m Q u o t e E n c o d e r {
1 b y t e [ ] e n c o d e ( I t e m Q u o t e i t e m ) t h r o w s E x c e p t i o n ;
2 }
ItemQuoteEncoder.java
The speci f i cat i on of t he cor r es pondi ng decodi ng f unct i onal i t y is gi ven by t he ItemQuot-
eDecoder i nt erface, whi ch has me t hods for par si ng mes s ages r ecei ved via s t r eams or in Dat a-
I 3.4 Implementing Wire Formats in Java 4
gramPackets. Each met hod per f or ms the same function: extracting the i nf or mat i on for one
message and ret urni ng an ItemQuote i nst ance cont ai ni ng the i nformat i on.
ItemQuoteDecoder.java
0 i m p o r t j a v a . i o . * ; / / f o r I n p u t S t r e a m a n d I O E x c e p t i o n
1 i m p o r t j a v a . n e t . * ; / / f o r D a t a g r a m P a c k e t
2
3 p u b l i c i n t e r f a c e I t e m Q u o t e D e c o d e r {
4 I t e m Q u o t e d e c o d e ( I n p u t S t r e a m s o u r c e ) t h r o w s I O E x c e p t i o n ;
5 I t e m Q u o t e d e c o d e ( D a t a g r a m P a c k e t p a c k e t ) t h r o w s I O E x c e p t i o n ;
6 }
ItemQuoteDecoder.java
Sections 3.4.1 and 3.4.2 pr esent two different i mpl ement at i ons for these interfaces: one usi ng
a text represent at i on, the other, a hybri d encoding.
3.4.1 Text-Oriented Representation
Clearly we can r epr esent the It emQuot e i nf or mat i on as text. One possibility is to simply
t ransmi t the out put of the t oSt r i ng( ) met hod usi ng a suitable charact er encoding. To simplify
parsing, the appr oach in this section uses a different represent at i on, in whi ch the values of
itemNumber, itemDescription, and so on are t r ansmi t t ed as a sequence of del i mi t ed text fields.
The sequence of fields is as follows:
<Item Number> <Description> <Quantity> <Price> (Discount?) (In Stock?>
The Item Number field (and the ot her integer-valued fields, Quant i t y and Price) cont ai n a
sequence of decimal digit charact ers followed by a space charact er (the delimiter). The Descrip-
tion field is j ust the descri pt i on text. However, because the text itself may include the space
character, we have to use a different delimiter; we choose the newline character, r epr esent ed
as \n in Java, as the delimiter for this field.
Boolean values can be encoded in several different ways. One possi bi l i t y is to include the
string "t rue" or the string "fal se", according to the value of the variable. A more compact
appr oach (and the one used here) is to encode bot h values (discounted and inStock) in a single
field; the field cont ai ns the charact er ' 8' if discounted is true, indicating t hat the i t em is
di scount ed, and the c h a r a c t e r ' s ' if inStock is true, indicating t hat the i t em is in stock. The
absence of a charact er indicates t hat the cor r espondi ng bool ean is fal se, so this field may be
empty. Again, a different delimiter (\n) is used for this final field, to make it slightly easier to
recognize the end of the message even when this field is empty. A quot e for 23 uni t s of i t em
number 12345, whi ch has the descri pt i on "AAA Battery" and price $14.45, and whi ch is bot h
in stock and di scount ed, woul d be r epr esent ed as
1 2 3 4 5 A A A B a t t e r y \ n 2 3 1 4 4 5 d s \ n
48 Chapter 3" Sending and Receiving Messages m
Const ant s needed by bot h the encoder and the decoder are defined in the ItemQuoteText-
Const interface, whi ch defines "ISO8859_1" as the default encodi ng (we could j ust as easily
have used any ot her encodi ng as the default) and 1024 as the maxi mum l engt h (in bytes) of
an encoded message. Limiting the l engt h of an encoded message limits the flexibility of the
prot ocol , but it also provi des for sanity checks by the receiver.
I t e m Qu o t e T e x t C o n s t . j a v a
O p u b l i c i n t e r f a c e I t e m O u o t e T e x t C o n s t {
1 p u b l i c s t a t i c f i n a l S t r i n g D E F A U L T _ E N C O D I N G = " I S 0 _ 8 8 5 9 _ I " ;
2 p u b l i c s t a t i c f i n a l i n t M A X _ W I R E _ L E N G T H = 1 0 2 4 ;
3 }
I t e m Q u o t e E n c o d e r T e x t i m p l e m e n t s t h e t e x t e n c o d i n g .
I t e mQu o t e E n c o d e r T e x t . j a v a
I t e m Qu o t e T e x t C o n s t . j a v a
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
O i m p o r t j a v a . i o . * ; / / f o r B y t e A r r a y O u t p u t S t r e a m a n d O u t p u t S t r e a m W r i t e r
1
2 p u b l i c c l a s s I t e m Q u o t e E n c o d e r T e x t i m p l e m e n t s I t e m O u o t e E n c o d e r , I t e m O u o t e T e x t C o n s t {
p r i v a t e S t r i n g e n c o d i n g ; / / C h a r a c t e r e n c o d i n g
p u b l i c I t e m Q u o t e E n c o d e r T e x t ( ) {
e n c o d i n g = D E F A U L T _ E N C O D I N G ;
}
p u b l i c I t e m Q u o t e E n c o d e r T e x t ( S t r i n g e n c o d i n g ) {
t h i s . e n c o d i n g = e n c o d i n g ;
}
p u b l i c b y t e [ ] e n c o d e ( I t e m Q u o t e i t e m ) t h r o w s E x c e p t i o n {
B y t e A r r a y O u t p u t S t r e a m b u f = n e w B y t e A r r a y O u t p u t S t r e a m ( ) ;
O u t p u t S t r e a m W r i t e r o u t = n e w O u t p u t S t r e a m W r i t e r ( b u f , e n c o d i n g ) ;
o u t . w r i t e ( i t e m . i t e m N u m b e r + .... );
i f ( i t e m . i t e m D e s c r i p t i o n . i n d e x O f ( ' \ n ' ) != - i )
t h r o w n e w l O E x c e p t i o n ( " I n v a l i d d e s c r i p t i o n ( c o n t a i n s n e w l i n e ) " ) ;
o u t . w r i t e ( i t e m . i t e m D e s c r i p t i o n + " \ n " + i t e m . q u a n t i t y + .... +
i t e m . u n i t P r i c e + .... );
i f ( i t e m . d i s c o u n t e d )
o u t . w r i t e ( ' d ' ) ; / / O n l y i n c l u d e ' d' i f d i s c o u n t e d
i f ( i t e m . i n S t o c k )
o u t . w r i t e ( ' s ' ) ; / / O n l y i n c l u d e ' s' i f i n s t o c k
1 3.4 Implementing Wire Formats in Java 49
26
27
28
29
30
31
32
}
}
o u t . w r i t e ( ' \ n ' ) ;
o u t . f l u s h ( ) ;
i f ( b u f . s i z e ( ) > M A X _ W I R E _ L E N G T H )
t h r o w n e w l O E x c e p t i o n ( " B n c o d e d l e n g t h t o o l o n g " ) ;
r e t u r n b u f . t o B y t e A r r a y ( ) ;
ItemQuoteEncoderText.java
1. Const r uct or s: lines 6-12
If no encodi ng is explicitly specified, we use the defaul t encodi ng specified in the const ant
interface.
2. encode() met hod: lines 14-31
9 Cr eat e an o ut p ut buf f er : lines 15-16
A ByteArray0utputStream collects the byt es to be ret urned. Wrapping it in an Out-
put Wri t er allows us to take advant age of the l at t er' s met hods for convert i ng strings
to bytes.
9 Wri te t he first i nt eger, f ol l owed by a space del i mi t er: line 17
9 Ch e c k f or del i mi t er: lines 18-19
Make sure t hat the field delimiter is not cont ai ned in the field itself. If it is, t hrow an
exception.
9 Out put itemDescription a nd ot he r i nt eg er s : lines 20-21
9 Wri te t he f l ag c ha r a c t e r s i f t he b o o l e a n s ar e true: lines 22-25
9 Wri te t he de l i mi t e r f or t he flag field: line 26
9 F l us h t he o ut p ut s t r eam: lines 27-29
Flush everything to the underl yi ng stream, and call si ze( ) to check t hat the resul t i ng
byte sequence is not too long. The l engt h rest ri ct i on allows the receiver to know how
big a buffer is needed to receive into a DatagramPacket. (For st r eam communi cat i on,
this is not necessary, but it is still convenient.)
9 Re t ur n t he b y t e ar r ay f r o m t he o ut p ut s t r eam: line 30
The decodi ng class ItemQuoteDecoderText si mpl y inverts the encodi ng process.
ItemQuoteDecoderText.java
0 i m p o r t j a v a . i o . * ; / / f o r I n p u t S t r e a m , B y t e A r r a y I n p u t S t r e a m , a n d I O E x c e p t i o n
1 i m p o r t j a v a . n e t . * ; / / f o r D a t a g r a m P a c k e t
2
3 p u b l i c c l a s s I t e m Q u o t e D e c o d e r T e x t i m p l e m e n t s I t e m Q u o t e D e c o d e r , I t e m Q u o t e T e x t C o n s t {
4
5 p r i v a t e S t r i n g e n c o d i n g ; / / C h a r a c t e r e n c o d i n g
50 Chapter 3: Sending and Receiving Messages []
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
31
32
33
34
35
36
p u b l i c I t e m O u o t e D e c o d e r T e x t ( ) {
e n c o d i n g = D E F A U L T _ E N C O D I N G ;
}
p u b l i c I t e m O u o t e D e c o d e r T e x t ( S t r i n g e n c o d i n g ) {
t h i s . e n c o d i n g = e n c o d i n g ;
}
p u b l i c I t e m Q u o t e d e c o d e ( I n p u t S t r e a m w i r e ) t h r o w s l O E x c e p t i o n {
S t r i n g i t e m N o , d e s c r i p t i o n , q u a n t , p r i c e , f l a g s ;
b y t e [ ] s p a c e = " " . g e t B y t e s ( e n c o d i n g ) ;
b y t e [ ] n e w l i n e = " \ n " . g e t B y t e s ( e n c o d i n g ) ;
i t e m N o = n e w S t r i n g ( F r a m e r . n e x t T o k e n ( w i r e , s p a c e ) , e n c o d i n g ) ;
d e s c r i p t i o n = n e w S t r i n g ( F r a m e r . n e x t T o k e n ( w i r e , n e w l i n e ) , e n c o d i n g ) ;
q u a n t = n e w S t r i n g ( F r a m e r . n e x t T o k e n ( w i r e , s p a c e ) , e n c o d i n g ) ;
p r i c e = n e w S t r i n g ( F r a m e r . n e x t T o k e n ( w i r e , s p a c e ) , e n c o d i n g ) ;
f l a g s = n e w S t r i n g ( F r a m e r . n e x t T o k e n ( w i r e , n e w l i n e ) , e n c o d i n g ) ;
r e t u r n n e w I t e m Q u o t e ( L o n g . p a r s e L o n g ( i t e m N o ) , d e s c r i p t i o n ,
I n t e g e r . p a r s e l n t ( q u a n t ) ,
I n t e g e r . p a r s e l n t ( p r i c e ) ,
( f l a g s . i n d e x O f ( ' d ' ) != - i ) ,
( f l a g s . i n d e x O f ( ' s ' ) != - i ) ) ;
p u b l i c I t e m Q u o t e d e c o d e ( D a t a g r a m P a c k e t p ) t h r o w s l O E x c e p t i o n {
B y t e A r r a y l n p u t S t r e a m p a y l o a d =
n e w B y t e A r r a y l n p u t S t r e a m ( p . g e t D a t a ( ) , p . g e t O f f s e t ( ) , p . g e t L e n g t h ( ) ) ;
r e t u r n d e c o d e ( p a y l o a d ) ;
}
ItemQuoteDecoderText.java
1. Var i abl es and c ons t r uc t or s : lines 5-13
9 Encodi ng: line 5
The encodi ng us ed in t he decoder mus t be t he same as in t he encoder!
9 Cons t r uct or s : lines 7-13
If no encodi ng is gi ven at cons t r uct i on t i me, t he def aul t def i ned in TtemQuoteDecoder-
TextConst is used.
2. St r eam decode(): lines 15-29
9 Conve r t del i mi t er s" l i nes 17-18
We get t he encoded f or m of t he del i mi t er s ahead of time, for efficiency.
I 3.4 Implementing Wire Formats in Java 5 |
9 Call t he n e x t T o k e n ( ) me t h od for each field: lines 19-23
For each field, we call Framer. nextToken() wi t h the appropri at e del i mi t er and convert
the resul t according to the specified encoding.
9 Const r uct ItemQuote: lines 24-28
Convert to native types usi ng the wr apper conversi on met hods and test for the
presence of the flag charact ers in the last field.
3. Packet decode(): lines 31-35
Extract the data, convert to a stream, and call the st ream decode() met hod.
3.4.2 Combined Data Representation
Our next encodi ng r epr esent s the integers of the ItemQuote as fixed-size, bi nary numbers:
i t emNumber as 64 bits, and quantity and unitPrice as 32 bits. It encodes the bool ean values as
flag bits, whi ch occupy the smallest possible space in an encoded message. Also, the variable-
l engt h string itemDescription is encoded in a field wi t h an explicit l engt h indication. The bi nary
encoding and decodi ng share coding const ant s in the ItemQuoteBinConst interface.
I t e mQu o t e Bi nCon s t . j a v a
O p u b l i c i n t e r f a c e I t e m Q u o t e B i n C o n s t {
p u b l i c s t a t i c f i n a l S t r i n g D E F A U L T _ E N C O D I N G = " I S 0 _ 8 8 5 9 _ i " ;
p u b l i c s t a t i c f i n a l i n t D I S C O U N T _ F L A G = 1 < < 7;
p u b l i c s t a t i c f i n a l i n t I N _ S T O C K _ F L A G = 1 < < 0;
p u b l i c s t a t i c f i n a l i n t M A X _ D E S C _ L E N = 2 5 5 ;
p u b l i c s t a t i c f i n a l i n t M A X _ W I R E _ L E N G T H = 1 0 2 4 ;
ItemQuoteEncoderBin i mpl ement s the bi nary encoding.
I t e mQu o t e Bi n Co n s t . j a v a
I t e mQu o t e E ncode r Bi n . j a v a
0 i m p o r t j a v a . i o . * ;
I
2
3
4
5
6
7
8
9
/ / f o r B y t e A r r a y O u t p u t S t r e a m a n d D a t a O u t p u t S t r e a m
p u b l i c c l a s s I t e m Q u o t e E n c o d e r B i n i m p l e m e n t s I t e m Q u o t e E n c o d e r , I t e m Q u o t e B i n C o n s t {
p r i v a t e S t r i n g e n c o d i n g ; / / C h a r a c t e r e n c o d i n g
p u b l i c I t e m Q u o t e E n c o d e r B i n ( ) {
e n c o d i n g = D E F A U L T _ E N C O D I N G ;
}
5 2 Chapter 3: Sending and Receiving Messages []
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
31
32
33
34
35
p u b l i c I t e m Q u o t e E n c o d e r B i n ( S t r i n g e n c o d i n g ) {
t h i s . e n c o d i n g = e n c o d i n g ;
}
p u b l i c b y t e [ ] e n c o d e ( I t e m Q u o t e i t e m ) throws E x c e p t i o n {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(buf);
out.writeLong(item.itemNumber);
out . wr i t eI nt ( i t em. quant i t y) ;
out . wr i t eI nt ( i t em. uni t Pr i ce) ;
byte flags = O;
i f (item.discounted)
flags ]= DISCOUNT_FLAG;
i f (item.inStock)
f l a g s I= I N _ S T O C K _ F L A G ;
o u t . w r i t e B y t e ( f l a g s ) ;
b y t e [ ] e n c o d e d D e s c = i t e m . i t e m D e s c r i p t i o n . g e t B y t e s ( e n c o d i n g ) ;
i f ( e n c o d e d D e s c . l e n g t h > M A X _ D E S C _ L E N )
t h r o w n e w I O E x c e p t i o n ( " I t e m D e s c r i p t i o n e x c e e d s e n c o d e d l e n g t h l i m i t " ) ;
o u t . w r i t e B y t e ( e n c o d e d D e s c . l e n g t h ) ;
o u t . w r i t e ( e n c o d e d D e s c ) ;
o u t . f l u s h ( ) ;
r e t u r n b u f . t o B y t e A r r a y ( ) ;
I t e m Qu o t e E n c o d e r Bi n . j a v a
1. Const ant s, vari abl es, and const r uct or s: lines 4-12
2. encode(): lines 14-34
9 Set up Out put : lines 16-17
Again, a ByteArray0utputStream collects the byt es of the encoded message. Encapsu-
lating the ByteArray0utputStream in a Data0utputStream allows use of its met hods for
writing bi nary integers.
9 Write integers" lines 18-20
The writeLong() met hod writes the l ong' s 8 byt es to the st ream in big-endian order.
Similarly, wr i t eI nt () out put s 4 bytes.
9 Write bool eans as flags: lines 21-26
Encode each bool ean usi ng a single bit in a flag byte. Initialize the flag byte to O, t hen
set the appropri at e bits to 1, if either discounted or inStock is true. (The bits are defined
in the ItemQuoteBinConst interface to be the most and least significant bits of the byte,
respectively.) Write the byte to the stream.
9 Conver t descr i pt i on st ri ng to byt es: line 2 7
Al t hough Data0utDutStream nrovi des met hods for writing St ri ngs, it SUDDOrts only one
! 3.4 Implementing Wire Formats in Java 5
fixed encoding, namely, UTF-8. Because we want to suppor t alternative encodings, we
convert the string to byt es explicitly.
9 Check des cr i pt i on l ength: lines 28-29
We are going to use an explicit l engt h encodi ng for the string, wi t h a single byte giving
the length. The biggest value t hat byte can cont ai n is 255 bytes, so the l engt h of the
encoded string must not exceed 255 bytes. If it does, we t hrow an exception.
9 Write e nc ode d string: lines 30-31
Write the l engt h of the encoded string, followed by the byt es in the buffer.
9 Fl ush out put st r eam, r et ur n byt es: l ine 32
Ensure t hat all byt es are flushed from the Data0utputStream to the underl yi ng byte
buffer.
ItemQuoteDecoderBin i mpl ement s the correspondi ng decoder function.
I t e m Qu o t e De c o d e r Bi n . j a v a
0 i m p o r t j a v a . i o . * ; / / f o r B y t e A r r a y I n p u t S t r e a m
1 i m p o r t j a v a . n e t . * ; / / f o r D a t a g r a m P a c k e t
2
3 p u b l i c c l a s s I t e m Q u o t e D e c o d e r B i n i m p l e m e n t s I t e m Q u o t e D e c o d e r , I t e m Q u o t e B i n C o n s t {
4
5 p r i v a t e S t r i n g e n c o d i n g ; / / C h a r a c t e r e n c o d i n g
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
p u b l i c I t e m Q u o t e D e c o d e r B i n ( ) {
e n c o d i n g = D E F A U L T _ E N C O D I N G ;
}
p u b l i c I t e m Q u o t e D e c o d e r B i n ( S t r i n g e n c o d i n g ) {
t h i s . e n c o d i n g = e n c o d i n g ;
}
p u b l i c I t e m Q u o t e d e c o d e ( I n p u t S t r e a m w i r e ) t h r o w s l O E x c e p t i o n {
b o o l e a n d i s c o u n t e d , i n S t o c k ;
D a t a l n p u t S t r e a m s r c = n e w D a t a I n p u t S t r e a m ( w i r e ) ;
l o n g i t e m N u m b e r = s r c . r e a d L o n g ( ) ;
i n t q u a n t i t y = s r c . r e a d I n t ( ) ;
i n t u n i t P r i c e = s r c . r e a d l n t ( ) ;
b y t e f l a g s = s r c . r e a d B y t e ( ) ;
i n t s t r i n g L e n g t h = s r c . r e a d ( ) ; / / R e t u r n s a n u n s i g n e d b y t e a s a n i n t
i f ( s t r i n g L e n g t h = = - i )
t h r o w n e w E O F E x c e p t i o n ( ) ;
b y t e [ ] s t r i n g B u f = n e w b y t e [ s t r i n g L e n g t h ] ;
s r c . r e a d F u l l y ( s t r i n g B u f ) ;
S t r i n g i t e m D e s c = n e w S t r i n g ( s t r i n g B u f , e n c o d i n g ) ;
r e t u r n n e w I t e m Q u o t e ( i t e m N u m b e r , i t e m D e s c , q u a n t i t y , u n i t P r i c e ,
( ( f l a g s & D I S C O U N T _ F L A G ) = = D I S C O U N T _ F L A G ) ,
( ( f l a g s & I N _ S T O C K _ F L A G ) = = I N _ S T O C K _ F L A G ) ) ;
54 Chapter 3: Sending and Receiving Messages 1
32
33
34
35
36
37
38
p u b l i c I t e m Q u o t e d e c o d e ( D a t a g r a m P a c k e t p ) t h r o w s l O E x c e p t i o n {
B y t e A r r a y I n p u t S t r e a m p a y l o a d =
n e w B y t e A r r a y l n p u t S t r e a m ( p . g e t D a t a ( ) , p . g e t O f f s e t ( ) , p . g e t L e n g t h ( ) ) ;
r e t u r n d e c o d e ( p a y l o a d ) ;
}
ItemQuoteDecoderBin.java
1. Const ant s, var i abl es, and const r uct or s: lines 5-13
2 . Str eam decode: lines 15-31
9 Wrap the InputStream: line 17
Using the given InputStream, const ruct a DataInputStream so we can make use of the
met hods readLong() and r eadI nt ( ) for readi ng bi nary dat a t ypes from the input.
9 Read i nteger s: lines 18-20
Read the integers back in the same order t hey were wri t t en out. The readLong()
met hod reads 8 byt es and const ruct s a (signed) l ong usi ng big-endian byt e ordering.
The r eadI nt ( ) met hod reads 4 byt es and does the same thing. Either will t hr ow an
EOFException if the st ream ends before the requisite number of byt es is read.
9 Read flag byte: line 2 1
The flag byt e is next; the values of the individual bits will be checked later.
9 Read str i ng l ength: lines 22-24
The next byte cont ai ns the l engt h of the encoded string. Note t hat we use the read()
met hod, whi ch r et ur ns the cont ent s of the next byte read as an integer bet ween 0 and
255 (or -1), and t hat we read it into an int. If we read it into a byt e (which is signed),
we woul d not be able to di st i ngui sh bet ween the case where the l engt h is 255 and
the case where the st ream ends pr emat ur el y- - bot h woul d r et ur n -1, since the signed
i nt er pr et at i on of the 8-bit bi nary r epr esent at i on of 255 is -1.
9 Al l ocat e buf f er and r ead e nc ode d string: lines 25-26
Once we know how long the encoded string is, we allocate a buffer and call r eadFul l y( ) ,
whi ch does not r et ur n until enough byt es have been read to fill the given buffer.
r eadFul l y( ) will t hrow an F,0FException if the st ream ends before the buffer is filled.
Note the advant age of the length-prefixed St ri ng represent at i on: byt es do not have to
be i nt er pr et ed as charact ers until you have t hem all.
9 Check flags: lines 29-30
The expressi ons used as par amet er s in the call to the const ruct or illustrate the stan-
dard met hod of checking whet her a part i cul ar bit is set (equal to 1) in an integer type.
3. Packet decode: di nes 33- 37
Simply wrap the packer' s dat a in a ByteArrayInputStream and pass to the st ream-decodi ng
met hod.
[] 3.4 Implementing Wire Formats in Java 5
3. 4. 3 Sending and Receiving
The encodi ngs pr e s e nt e d above can be us e d wi t h bot h Socket s and DatagramSockets. We s how
t he TCP us age first.
SendTCP.java
0 import j ava. i o. *; / / for Input / 0ut put St ream
1 import j ava. net . *; / / for Socket
2
3 public cl ass SendTCP {
4
5 publ i c s t a t i c void mai n(St ri ng ar gs[ ] ) throws Exception {
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 }
i f ( ar gs. l engt h != 2) / / Test for cor r ect # of args
throw new Il l egal Argument Except i on("Paramet er(s): <Destination> <Port>");
I n e t A d d r e s s d e s t A d d r = I n e t A d d r e s s . g e t B y N a m e ( a r g s [ O ] ) ;
i n t d e s t P o r t = I n t e g e r . p a r s e l n t ( a r g s [ l ] ) ;
/ / D e s t i n a t i o n a d d r e s s
/ / D e s t i n a t i o n p o r t
Socket sock = new Socket(destAddr, dest Por t ) ;
ItemQuote quote = new ItemQuote(1234567890987654L, "5mm Super Widgets",
1000, 12999, true, false);
/ / S e n d t e x t - e n c o d e d q u o t e
I t e m Q u o t e E n c o d e r c o d e r = n e w I t e m Q u o t e E n c o d e r T e x t ( ) ;
b y t e [ ] c o d e d Q u o t e = c o d e r . e n c o d e ( q u o t e ) ;
S y s t e m . o u t . p r i n t l n ( " S e n d i n g T e x t - E n c o d e d Q u o t e (" +
c o d e d Q u o t e . l e n g t h + " b y t e s ) : ");
S y s t e m . o u t . p r i n t l n ( q u o t e ) ;
s o c k . g e t O u t p u t S t r e a m ( ) . w r i t e ( c o d e d Q u o t e ) ;
/ / R e c e i v e b i n a r y - e n c o d e d q u o t e
I t e m Q u o t e D e c o d e r d e c o d e r = n e w I t e m Q u o t e D e c o d e r B i n ( ) ;
I t e m Q u o t e r e c e i v e d Q u o t e = d e c o d e r . d e c o d e ( s o c k . g e t l n p u t S t r e a m ( ) ) ;
S y s t e m . o u t . p r i n t l n ( " R e c e i v e d B i n a r y - E n c o d e Q u o t e : ") ;
S y s t e m . o u t . p r i n t l n ( r e c e i v e d Q u o t e ) ;
s o c k . c l o s e ( ) ;
SendTCP.java
56 Chapter 3: Sending and Receiving Messages 1
1. Socket set up: line 13
2. Send usi ng text encoding: lines 18-24
3. Receive usi ng binary encoding: lines 26- 30
RecvTCP.java
0 i m p o r t j a v a . i o . * ;
1 i m p o r t j a v a . n e t . * ;
2
3
4
5
6
7
8
9
i 0
i i
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 2
2 3
2 4
2 5
2 6
2 7 c l n t S o c k , c l o s e ( ) ;
2 8 s e r v S o c k , c l o s e ( ) ;
2 9 }
3 0 }
/ / f o r I n p u t / O u t p u t S t r e a m
/ / f o r S o c k e t a n d S e r v e r S o c k e t
p u b l i c c l a s s R e c v T C P {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g a r g s [ ] ) t h r o w s E x c e p t i o n {
i f ( a r g s . l e n g t h != i) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w I l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < P o r t > " ) ;
i n t p o r t = I n t e g e r . p a r s e I n t ( a r g s [ O ] ) ; / / R e c e i v i n g P o r t
S e r v e r S o c k e t s e r v S o c k = n e w S e r v e r S o c k e t ( p o r t ) ;
S o c k e t c l n t S o c k = s e r v S o c k , a c c e p t () ;
/ / R e c e i v e t e x t - e n c o d e d q u o t e
I t e m Q u o t e D e c o d e r d e c o d e r = n e w I t e m Q u o t e D e c o d e r T e x t ( ) ;
I t e m Q u o t e q u o t e = d e c o d e r . d e c o d e ( c l n t S o c k . g e t I n p u t S t r e a m ( ) ) ;
S y s t e m . o u t . p r i n t l n ( " R e c e i v e d T e x t - E n c o d e d Q u o t e : " ) ;
S y s t e m . o u t . p r i n t l n ( q u o t e ) ;
/ / Repeat quote with binary encoding, adding 10 cents to the pri ce
ItemQuoteEncoder encoder = new ItemQuoteEncoderBin();
quot e. uni t Pr i ce +: 10; / / Add 10 cents to uni t pri ce
Syst em. out . pri nt l n("Sendi ng ( bi nar y) . . . ");
clntSock, getOutputStream(), wri t e (encoder. encode (quote)) ;
RecvTCP.java
1. Socket setup: line 12
2 . Accept client connection: line 1 3
[] 3.4 Implementing Wire Formats in Java 5
3. Re c e i v e and pr i nt out a t e xt - e nc ode d me s s a g e : l i nes 1 5 - 1 9
4. Send a bi na r y - e nc ode d me s s a g e : l i nes 21-25
Note t hat bef or e sendi ng, we add 10 cent s to t he uni t pri ce gi ven in t he ori gi nal message.
To de mons t r a t e t he use of t he encodi ng and decodi ng cl asses wi t h dat agr ams , we i ncl ude
a si mpl e UDP s ender and recei ver. Since t hi s is very si mi l ar to t he TCP code, we do not i ncl ude
any code descr i pt i on.
SendUDP.java
0 i m p o r t j a v a . n e t . * ;
1 i m p o r t j a v a . i o . * ;
2
3
4
5
6
7
8
9
I 0
i i
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9 s o c k . c l o s e ( ) ;
3 0 }
3 1 }
/ / for DatagramSocket, DatagramPacket, and InetAddress
/ / for IOF.xception
p u b l i c c l a s s S e n d U D P {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g a r g s [ ] ) t h r o w s E x c e p t i o n {
i f ( a r g s . l e n g t h != 2 & & a r g s . l e n g t h != 3 ) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) ' < D e s t i n a t i o n > " +
" < P o r t > [ < e n c o d i n g ] " ) ;
I n e t A d d r e s s d e s t A d d r = I n e t A d d r e s s . g e t B y N a m e ( a r g s [ 0 ] ) ;
i n t d e s t P o r t = I n t e g e r . p a r s e I n t ( a r g s [ i] ) ;
/ / D e s t i n a t i o n address
/ / D e s t i n a t i o n port
ItemQuote quote = new I t e m Q u o t e ( 1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 L , "5mm Super Widgets",
1000, 12999, t r ue, f al s e) ;
D a t a g r a m S o c k e t s o c k = n e w D a t a g r a m S o c k e t ( ) ; / / U D P s o c k e t f o r s e n d i n g
ItemQuoteEncoder encoder = ( ar gs . l engt h == 3 ?
n e w I t e m Q u o t e E n c o d e r T e x t ( a r g s [ 2 ] ) '
new ItemQuoteEncoderText());
b y t e [ ] c o d e d Q u o t e = e n c o d e r . e n c o d e ( q u o t e ) ;
DatagramPacket message = new DatagramPacket(codedQuote, codedQuote.length,
destAddr, dest Port ) ;
sock. send(message) ;
i
SendUDP.java
58 Chapter 3: Sending and Receiving Messages []
RecvUDP.java
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
O import j ava. net . *; / / for DatagramSocket and DatagramPacket
1 import j ava. i o. *; / / for 10Exception
2
3 public class RecvUDP implements ItemQuoteTextConst {
4
5 public st at i c void main(String[] args) throws Exception {
6
i f (args. l engt h != 1 &&args. l engt h != 2) / / Test for correct # of args
throw new lllegalArgumentException("Parameter(s): <Port> [<encoding>]");
i n t p o r t = I n t e g e r . p a r s e l n t ( a r g s [ O ] ) ; / / R e c e i v i n g P o r t
DatagramSocket sock = new DatagramSocket(port); / / UDP socket for receiving
ItemQuoteDecoder decoder = (args. l engt h == 2 ? / / Which encoding
new ItemquoteDecoderText(args[1]) :
new ItemQuoteDecoderText() );
D a t a g r a m P a c k e t p a c k e t = n e w D a t a g r a m P a c k e t (
n e w b y t e [ M A X _ W I R E _ L E N G T H ] , M A X _ W I R E _ L E N G T H ) ;
s o c k . r e c e i v e ( p a c k e t ) ;
I t e m Q u o t e quote = d e c o d e r . d e c o d e ( p a c k e t ) ;
S y s t e m . o u t . p r i n t l n ( q u o t e ) ;
sock. cl ose();
RecvUDP.java
3.5 Wrapping Up
We have seen how Java dat a types can be encoded in different ways, and how messages can
be const r uct ed from vari ous types of i nformat i on. You may be aware t hat recent versi ons of
Java include serialization capabi l i t i es--t he Ser i al i zabl e and Ext er nal i zabl e i nt er f aces- - whi ch
provi de for i nst ances of suppor t i ng Java classes to be convert ed to and from byte sequences
very easily. It mi ght seem t hat having t hese interfaces available woul d eliminate the need for
what has been descri bed above, and t hat is to some ext ent true. However, it is not always the
case, for a couple of reasons.
First, the encoded forms pr oduced by Ser i al i zabl e may not be very efficient. They may
include i nf or mat i on t hat is meani ngl ess out si de the cont ext of the Java Virtual Machine (JVM),
and may also i ncur overhead to provi de flexibility t hat may not be needed. Second, Ser i al i zabl e
and Ext er nal i zabl e cannot be used when a different wire format has already been speci fi ed--
m 3.6 Exercises 59
for example, by a st andar di zed prot ocol . And finally, cust om-desi gned classes have to provi de
their own i mpl ement at i ons of the seri al i zat i on interfaces anyway.
A basic t enet of good prot ocol desi gn is t hat the prot ocol shoul d const rai n the imple-
ment or as little as possible and shoul d mi ni mi ze assumpt i ons about the pl at f or m on whi ch the
prot ocol will be i mpl ement ed. We t herefore avoid the use of Ser i al i zabl e and Ext er nal i zabl e
in this book, and i nst ead use more direct encodi ng and decodi ng met hods.
3. 6 Exerci ses
1. What happens if the Encoder uses a different encodi ng t han the Decoder?
2. Positive integers larger t han 231- 1 cannot be r epr esent ed as i nt s in Java, yet t hey can
be r epr esent ed as 32-bit bi nary numbers. Write a met hod to write such an integer to a
stream. It shoul d take a l ong and an Out put St r eam as paramet ers.
3. Rewrite the bi nary encoder so t hat the Item Descri pt i on is t er mi nat ed by "\ r \ n" i nst ead
of being l engt h encoded. Use Send/RecvTCP to t est this new encoding.
4. The nextToken() met hod of DelimitedInputStream assumes t hat either the delimiter or an
end-of-st ream (EoS) t ermi nat es a token; however, finding the EoS may be an error in some
prot ocol s. Rewrite nextToken() to include a second, bool ean paramet er. If the par amet er
value is t rue, t hen the EoS t ermi nat es a t oken wi t hout error; otherwise, the EoS generat es
an error.
c h a p t e r 4
Beyond the Basics
The client and server exampl es in Chapter 2 demonst rat e the basic model for program-
ming with sockets in Java. The next step is to apply these concept s in various programmi ng
models, such as multitasking, nonblocking I/O, and broadcast i ng.
4.1 Multitasking
Our basic TCP echo server from Chapter 2 handl es one client at a time. If a client connects
while anot her is already being serviced, the server will not echo the new client' s data until
it has finished with the current client, al t hough the new client will be able to send data as
soon as it connects. This type of server is known as an i t erat i ve s er ver . Iterative servers handle
clients sequentially, finishing with one client before servicing the next. They work best for
applications where each client requires a small, bounded amount of server connect i on time;
however, if the time to handle a client can be long, the wait experienced by subsequent clients
may be unacceptable.
To demonst r at e the problem, add a 10-second sleep using Thread. sl eep( ) after the Socket
const ruct or call in TCPEchoClient. java and experi ment with several clients si mul t aneousl y
accessing the TCP echo server. Here the sleep operat i on simulates an operat i on that takes
significant time, such as slow file or net work I/O. Note that a new client must wait for all
al ready-connect ed clients to complete before it gets service.
What we need is some way for each connect i on to proceed i ndependent l y, wi t hout
interfering with other connections. Java t hreads provide exactly that: a convenient mechani sm
allowing servers to handle many clients simultaneously. Using threads, a single application
can work on several tasks concurrently. In our echo server, we can give responsibility for each
client to an i ndependent l y executing thread. All of the exampl es we have seen so far consist
of a single thread, which simply executes the main() met hod.
In this section we describe two approaches to coding c o n c u r r e n t s er ver s , namely, t hr ead-
per- cl i ent , where a new t hread is spawned to handle each client connection, and t h r e a d pool ,
where a fixed, pr espawned set of t hreads work t oget her to handle client connections.
61
62 Chapter 4: Beyond the Basics []
4.1.1 Java Threads
Java provi des t wo approaches f or perf ormi ng a task i n a new thread: 1) def i mng a subclass
of the Thread class with a run() met hod t hat performs the task, and i nst ant i at i ng it; or 2)
defining a class t hat i mpl ement s the Runnable interface wi t h a run() met hod t hat performs the
task, and passi ng an instance of t hat class to the Thread constructor. In either case, the new
t hread does not begin execution until its s t a r t ( ) met hod is invoked. The first approach can
only be used for classes t hat do not already ext end some other class; therefore, we focus on the
second approach, which is always applicable. The Runnable interface contains a single met hod
prot ot ype:
p u b l i c v o i d r u n ( ) ;
When the s t ar t () met hod of an instance of Thread is invoked, the JVM causes the in-
st ance' s run() met hod to be executed in a new thread, concurrent l y with all others. Meanwhile,
the original t hread ret urns from its call to s t ar t () and continues its execution i ndependent l y.
(Note t hat directly calling the run() met hod of a Thread or Runnable instance has the normal
procedure-call semantics: the met hod is executed in the caller' s thread.) The exact interleaving
of t hread execution is det ermi ned by several factors, including the i mpl ement at i on of the JVM,
the load, the underl yi ng OS, and the host configuration. For example, on a uni processor sys-
tem, t hreads share the processor sequentially; on a mul t i processor system, mul t i pl e t hreads
from the same application can run si mul t aneousl y on different processors.
In the following example, ThreadExample. java i mpl ement s the Runnable interface wi t h a
run() met hod t hat repeat edl y pri nt s a greeting to the syst em out put stream.
ThreadExample.java
0 p u b l i c c l a s s T h r e a d E x a m p l e i m p l e m e n t s R u n n a b l e {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private String greeting; / / Message to pri nt to console
p u b l i c T h r e a d E x a m p l e ( S t r i n g g r e e t i n g ) {
t h i s . g r e e t i n g = g r e e t i n g ;
}
p u b l i c v o i d r u n ( ) {
f o r ( ; ; ) {
S y s t e m . o u t . p r i n t l n ( T h r e a d . c u r r e n t T h r e a d ( ) . g e t N a m e ( ) + ": " + g r e e t i n g ) ;
t r y {
T h r e a d . s l e e p ( ( l o n g ) ( M a t h . r a n d o m ( ) * i 0 0 ) ) ; / / S l e e p 0 t o i 0 0 m i l l i s e c o n d s
} c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) { } / / W i l l n o t h a p p e n
}
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) {
n e w T h r e a d ( n e w T h r e a d E x a m p l e ( " H e l l o " ) ) . s t a r t ( ) ;
n 4.1 Multitasking 63
19
20
21
22
}
}
n e w T h r e a d ( n e w T h r e a d E x a m p l e ( " A l o h a " ) ) . s t a r t ( ) ;
n e w T h r e a d ( n e w T h r e a d E x a m p l e ( " C i a o " ) ) . s t a r t ( ) ;
Th read Exam pi e. j ava
1. Decl arat i on of i mpl ement at i on of t he Runnable interface: line 0
Since ThreadExample i mpl ement s the Runnable interface, it can be passed to the construc-
tor of Thread. If ThreadExample fails to provide a run() met hod, the compiler will complain.
2. Member var i abl es and const ruct or: lines 2-6
Each instance of ThreadExample contains its own greeting string.
3. run ( ): lines 8-15
Loop forever performing:
9 Print t he t hr ead name and i nst ance greet i ng: line 10
The static met hod Thread. current Thread() ret urns a reference to the t hread from
which it is called, and getName() ret urns a string containing the name of t hat thread.
9 Suspend t hread: lines 11-13
After printing its i nst ance' s greeting message, each t hread sleeps for a r andom amount
of time (between 0 and 100 milliseconds) by calling the static met hod Thread. sl eep(),
which takes the number of milliseconds to sleep as a paramet er. Math. random() ret urns
a r andom doubl e bet ween 0.0 and 1.0. Thread. sl eep() can be i nt errupt ed by anot her
thread, in which case an Int errupt edExcept i on is thrown. Our example does not include
an i nt errupt call, so the exception will not happen in this application.
4. main(): lines 17-21
Each of the three st at ement s in main() does the following: 1) creates a new instance
of ThreadExample with a different greeting string, 2) passes this new instance to the
const ruct or of Thread, and 3) calls the new Thread i nst ance' s s t ar t () met hod. Each t hread
i ndependent l y executes the run() met hod of ThreadExample, while the main() t hread
t ermi nat es. Note t hat the JVM does not t ermi nat e until all nondaemon (see Threads API)
t hreads t ermi nat e.
Upon execution, an interleaving of the three greeting messages is pri nt ed to the console.
The exact interleaving of the number s depends upon the factors ment i oned earlier.
4.1.2 Server Protocol
Since the two server approaches we are going to describe (thread-per-client and t hread pool)
are i ndependent of the particular client-server protocol, we want to be able to use the same
protocol code for both. The code for the echo protocol is given in the class EchoProtocol,
which encapsul at es the i mpl ement at i on of the server side of the echo protocol. The idea is
t hat the server creates a separat e instance of EchoProtocol for each connection, and protocol
64 Chapter 4: Beyond the Basics m
execut i on begi ns when r u n ( ) is called on an i nst ance. The code in r u n ( ) is al most i dent i cal to
t he connect i on handl i ng code in TCPEchoServer. java, except t hat a l oggi ng capabi l i t y (descri bed
short l y) has been added. The class i mpl ement s t he Runnable i nt erface, so we can creat e a t hr ead
t hat i nde pe nde nt l y execut es run(), or we can i nvoke run() directly.
EchoProtocol.java
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
31
32
33
34
35
36
37
38
39
i m p o r t j a v a . n e t . *;
i m p o r t j a v a . i o . * ;
i m p o r t j a v a . u t i l . *;
/ / f o r S o c k e t
/ / f o r l O E x c e p t i o n a n d I n p u t / O u t p u t S t r e a m
/ / f o r A r r a y L i s t
c l a s s E c h o P r o t o c o l i m p l e m e n t s R u n n a b l e {
s t a t i c p u b l i c f i n a l i n t B U F S I Z E = 32; / / S i z e ( i n b y t e s ) o f I / O b u f f e r
p r i v a t e S o c k e t c l n t S o c k ;
p r i v a t e L o g g e r l o g g e r ;
/ / C o n n e c t i o n s o c k e t
/ / L o g g i n g f a c i l i t y
p u b l i c E c h o P r o t o c o l ( S o c k e t c l n t S o c k , L o g g e r l o g g e r ) {
t h i s . c l n t S o c k = c l n t S o c k ;
t h i s . l o g g e r = l o g g e r ;
}
p u b l i c v o i d r u n ( ) {
A r r a y L i s t e n t r y = n e w A r r a y L i s t ( ) ;
e n t r y . a d d ( " C l i e n t a d d r e s s a n d p o r t = " +
c l n t S o c k . g e t l n e t A d d r e s s ( ) . g e t H o s t A d d r e s s ( ) + " : " +
c l n t S o c k . g e t P o r t ( ) ) ;
e n t r y . a d d ( " T h r e a d = " + T h r e a d . c u r r e n t T h r e a d ( ) . g e t N a m e ( ) ) ;
t r y {
/ / G e t t h e i n p u t a n d o u t p u t I / O s t r e a m s f r o m s o c k e t
I n p u t S t r e a m i n = c l n t S o c k , g e t I n p u t S t r e a m ( ) ;
O u t p u t S t r e a m o u t = c l n t S o c k . g e t O u t p u t S t r e a m ( ) ;
i n t r e c v U s g S i z e ; / / S i z e o f r e c e i v e d m e s s a g e
i n t t o t a l B y t e s E c h o e d = 0 ; / / B y t e s r e c e i v e d f r o m c l i e n t
b y t e [ ] e c h o B u f f e r = n e w b y t e [ B U F S I Z E ] ; / / R e c e i v e B u f f e r
/ / R e c e i v e u n t i l c l i e n t c l o s e s c o n n e c t i o n , i n d i c a t e d b y - i
w h i l e ( ( r e c v U s g S i z e = i n . r e a d ( e c h o B u f f e r ) ) != - i ) {
o u t . w r i t e ( e c h o B u f f e r , O, r e c v M s g S i z e ) ;
t o t a l B y t e s E c h o e d + = r e c v U s g S i z e ;
}
e n t r y . a d d ( " C l i e n t f i n i s h e d ; e c h o e d " + t o t a l B y t e s E c h o e d + " b y t e s . " ) ;
} c a t c h ( I O E x c e p t i o n e ) {
e n t r y . a d d ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
}
m 4.1 Multitasking 65
40
41
42
43
44
45
46
47
48
49
}
}
t r y { / / C l o s e s o c k e t
c l n t S o c k . c l o s e ( ) ;
} c a t c h ( I O E x c e p t i o n e ) {
e n t r y . a d d ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
}
l o g g e r , w r i t e E n t r y ( e n t r y ) ;
EchoProtocol.java
1. Decl arat i on of i mpl ement at i on of the Runnable interface: line 4
2. Member vari abl es and const ruct or: lines 7-13
Each instance of EchoProtocol contains a socket for the connection and a reference to the
logger.
3. run(): lines 15-48
Impl ement the echo protocol:
9 Write the client and t hr ead i nf or mat i on to a buffer: lines 16-20
ArrayList is a dynamically sized container of Objects. The add() met hod of ArrayList
inserts the specified object at the end of the list. In this case, the i nsert ed object is a
String. Each element of the ArrayList represent s a line of out put to the logger.
9 Execute the echo prot ocol : lines 22-45
9 Write the el ement s (one per line) of the A r r a y L i s t i nst ance to the logger: line 47
The logger allows for synchroni zed report i ng of t hread creation and client completion,
so that entries from different t hreads are not interleaved. This facility is defined by the Logger
interface, which has met hods for writing strings or object collections.
Logger.java
0 i m p o r t j a v a . u t i l . * ; / / f o r C o l l e c t i o n
1
2 p u b l i c i n t e r f a c e L o g g e r {
3 p u b l i c v o i d w r i t e E n t r y ( C o l l e c t i o n e n t r y ) ; / / W r i t e l i s t o f l i n e s
4 p u b l i c v o i d w r i t e E n t r y ( S t r i n g e n t r y ) ; / / W r i t e s i n g l e l i n e
5 }
Logger.java
66 Chapter 4: Beyond the Basics 1
wr i t eEnt r y( ) logs the given string or object collection. How it is l ogged depends on the
i mpl ement at i on. One possibility is to send the log messages to the console.
Con s ol e L ogge r ja va
0
1
2
3
4
5
6
7
8
9
10
11
12
13
i m p o r t j a v a . u t i l . * ; / / f o r C o l l e c t i o n a n d I t e r a t o r
c l a s s C o n s o l e L o g g e r i m p l e m e n t s L o g g e r {
p u b l i c s y n c h r o n i z e d v o i d w r i t e E n t r y ( C o l l e c t i o n e n t r y ) {
f o r ( I t e r a t o r l i n e = e n t r y . i t e r a t o r ( ) ; l i n e . h a s N e x t ( ) ; )
S y s t e m . o u t . p r i n t l n ( l i n e . n e x t ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ) ;
}
p u b l i c s y n c h r o n i z e d v o i d w r i t e E n t r y ( S t r i n g e n t r y ) {
S y s t e m . o u t . p r i n t l n ( e n t r y ) ;
S y s t e m . o u t . p r i n t l n ( ) ;
}
Con sol e Log ge r . j a va
Anot her possibility is to write the log messages to a file specified in the const ruct or, as
in the following:
F i l e L ogge r . j a v a
0 i m p o r t j a v a . i o . * ;
1 i m p o r t j a v a . u t i l . * ;
2
3
4
5
6
7
8
9
1 0
i i
1 2
1 3
1 4
1 5
1 6
/ / f o r P r i n t W r i t e r a n d F i l e W r i t e r
/ / f o r C o l l e c t i o n a n d I t e r a t o r
c l a s s F i l e L o g g e r i m p l e m e n t s L o g g e r {
P r i n t W r i t e r o u t ; / / L o g f i l e
p u b l i c F i l e L o g g e r ( S t r i n g f i l e n a m e ) t h r o w s l O E x c e p t i o n {
o u t = n e w P r i n t W r i t e r ( n e w F i l e W r i t e r ( f i l e n a m e ) , t r u e ) ;
}
p u b l i c s y n c h r o n i z e d v o i d w r i t e E n t r y ( C o l l e c t i o n e n t r y ) {
f o r ( I t e r a t o r l i n e = e n t r y . i t e r a t o r ( ) ; l i n e . h a s N e x t ( ) ; )
o u t . p r i n t l n ( l i n e , n e x t ( ) ) ;
o u t . p r i n t l n ( ) ;
}
/ / C r e a t e l o g f i l e
[] 4.1 Multitasking 67
17
18
19
20
21
p u b l i c s y n c h r o n i z e d v o i d w r i t e E n t r y ( S t r i n g e n t r y ) {
o u t . p r i n t l n ( e n t r y ) ;
o u t . p r i n t l n ( ) ;
}
F i l e L ogge r . j a v a
We are now r eady to i nt r oduce some di fferent appr oaches to concur r ent servers.
4.1.3 Thread-per-Client
In a thread-per-client server, a new t hr ead is cr eat ed to handl e each connect i on. The server
execut es a loop t hat r uns forever, l i st eni ng for connect i ons on a specified por t and r epeat edl y
accept i ng an i ncomi ng connect i on f r om a client and t hen spawni ng a new t hr ead to handl e
t hat connect i on.
TCPEchoServerThread. j ava i mpl ement s the t hread-per-cl i ent archi t ect ure. It is very similar
to the i t erat i ve server, usi ng a single indefinite loop to receive and pr ocess client request s. The
mai n di fference is t hat it creat es a t hr ead to handl e the connect i on i nst ead of handl i ng it
directly. (This is possi bl e because EchoProtoeol i mpl ement s the Runnable interface. )
TCP Ec hoSe r ye r Th r ead . j a va
0 i m p o r t j a v a . n e t . * ; / / f o r S o c k e t , S e r v e r S o c k e t , a n d I n e t A d d r e s s
1 i m p o r t j a v a . i o . * ; / / f o r I O E x c e p t i o n a n d I n p u t / 0 u t p u t S t r e a m
2
3 p u b l i c c l a s s T C P E c h o S e r v e r T h r e a d {
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
p u b l i c s t at i c v o i d main(String[] a r g s ) t h r o w s 1 0 E x c e p t i o n {
i f ( a r g s . l e n g t h != I ) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w I l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < P o r t > " ) ;
i n t e c h o S e r v P o r t = I n t e g e r . p a r s e l n t ( a r g s [ O ] ) ; / / S e r v e r p o r t
/ / C r e a t e a s e r v e r s o c k e t t o a c c e p t c l i e n t c o n n e c t i o n r e q u e s t s
S e r v e r S o c k e t s e r v S o c k = n e w S e r v e r S o c k e t ( e c h o S e r v P o r t ) ;
Logger logger = new ConsoleLogger() ; / / L o g m e s s a g e s t o c o n s o l e
/ / R u n f o r e v e r , a c c e p t i n g a n d s p a w n i n g t h r e a d s t o s e r v i c e e a c h c o n n e c t i o n
f o r (; ;) {
t r y {
S o c k e t c l n t S o c k = s e r v S o c k . a c c e p t ( ) ; / / B l o c k w a i t i n g f o r c o n n e c t i o n
68 Chapter 4: Beyond the Basics []
21
22
23
24
25
26
27
28
29
30
31
}
}
E c h o P r o t o c o l p r o t o c o l = new E c h o P r o t o c o l ( c l n t S o c k , l o g g e r ) ;
T h r e a d t h r e a d = n e w T h r e a d ( p r o t o c o l ) ;
t h r e a d . s t a r t ( ) ;
l o g g e r . w r i t e E n t r y ( " C r e a t e d a n d s t a r t e d T h r e a d = " + t h r e a d . g e t N a m e ( ) ) ;
} c a t c h ( l O E x c e p t i o n e ) {
l o g g e r . w r i t e E n t r y ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
}
}
/* NOT REACHED */
TC P EchoSe r v e r T h r e a d . j a v a
1. Par ame t e r par s i ng and s e r v e r s o c k e t / l o g g e r creat i on: lines 7-15
2. Loop f or ever , handl i ng i ncomi ng connect i ons: lines 17-28
9 Accept an i ncomi ng connect i on" line 20
9 Cr eat e a pr ot ocol i nst ance t o handl e n e w c onne c t i on: line 21
Each connect i on get s its own i nst ance of EchoProtocol. Each i nst ance mai nt ai ns t he
st at e of its part i cul ar connect i on. The echo pr ot ocol has little i nt ernal state, but mor e
sophi st i cat ed pr ot ocol s may requi re subst ant i al amount s of state.
9 Creat e, st art , and l og a n e w t hread f or t he connect i on: lines 22-24
Since EchoProt ocol i mpl ement s the Runnable i nt erface, we can give our new i nst ance
to t he Thread const ruct or, and t he new t hr ead will execut e t he run() me t hod of
EchoProt ocol when s t a r t ( ) is i nvoked. The getName() me t hod of Thread r et ur ns a
St r i ng cont ai ni ng a name for t he new t hread.
9 Handl e e xce pt i on f r om accept ( ) : lines 25- 27
If some I/O error occurs, accept () t hr ows an IOException. In our earlier i t erat i ve echo
server (TCPEchoServer. java), the except i on is not handl ed, and such an error t er mi nat es
the server. Here we handl e the except i on by l oggi ng the error and cont i nui ng execut i on.
4. 1. 4 Factoring the Server
Our t hr eaded server does what we want it to, but t he code is not very reusabl e or ext ensi bl e.
First, t he echo pr ot ocol is har d- coded in t he server. What if we want an HTTP server i nst ead? We
coul d write an HTTPProtocol and repl ace t he i nst ant i at i on of EchoProtocol in main(); however,
we woul d have to revise main() and have a separ at e mai n class for each di fferent pr ot ocol t hat
we i mpl ement .
We want to be able to i nst ant i at e a pr ot ocol i nst ance of t he appr opr i at e t ype for each
connect i on wi t hout knowi ng any specifics about t he prot ocol , i ncl udi ng t he name of a con-
st ruct or. This pr obl em- - i nst ant i at i ng an obj ect wi t hout knowi ng details about its t ype- - ar i ses
f r equent l y in obj ect - or i ent ed pr ogr ammi ng, and t here is a st andar d solution: use a factory. A
II 4.1 Multitasking 69
factory object supplies instances of a particular class, hiding the details of how the instance
is created, such as what const ruct or is used.
For our prot ocol factory, we define the Prot ocol Fact ory interface to have a single method,
creat eProt ocol (), which takes Socket and Logger instances as argument s and ret urns an
instance i mpl ement i ng the desired protocol. Our prot ocol s will all i mpl ement the Runnable
interface, so that once we have an instance we can simply call run() (or s t ar t ( ) on a Thread
const ruct ed from the protocol instance) to execute the prot ocol for that connection. Thus, our
protocol factory ret urns instances that i mpl ement the Runnable interface:
ProtocolFactory.java
0 i m p o r t j a v a . n e t . * ; / / f o r S o c k e t
1
2 p u b l i c i n t e r f a c e P r o t o c o l F a c t o r y {
3 p u b l i c R u n n a b l e c r e a t e P r o t o c o l ( S o c k e t c l n t S o c k , L o g g e r l o g g e r ) ;
4 }
Protocol Factory.java
We now need to i mpl ement a protocol factory for the echo protocol. The factory class is
simple. All it does is ret urn a new instance of EchoProtocol whenever creat eProt ocol () is called.
EchoProtocolFactory.java
0 i m p o r t j a v a . n e t . * ; / / f o r S o c k e t
1
2 p u b l i c c l a s s E c h o P r o t o c o l F a c t o r y i m p l e m e n t s P r o t o c o l F a c t o r y {
3 public Runnable createProtocol(Socket clntSock, Logger logger) {
4 return new EchoProtocol(clntSock, logger);
5 }
6 }
EchoProtocolFactory.java
We have factored out some of the details of prot ocol instance creation from our server,
so that the various iterative and concurrent servers can reuse the prot ocol code. However,
the server approach (iterative, thread-per-client, etc.) is still hard-coded in the main(). These
server approaches deal with how to dispatch each connection to the appropri at e handling
mechanism. To provide greater extensibility, we want to factor out the dispatching model from
the main() of TCPEchoServerThread. java so that we can use any dispatching model with any
protocol. Since we have many potential dispatching models, we define the Dispatcher interface
to hide the particulars of the threading strategy from the rest of the server code. It contains a
70 Chapter 4: Beyond the Basics []
single method, st art Di spat chi ng(), which tells the dispatcher to start handling clients accepted
via the given ServerSocket, creating protocol instances using the given ProtocolFactory, and
logging via the given Logger.
Di spat cher . j ava
0 i m p o r t j a v a . n e t . * ; / / f o r S e r v e r S o c k e t
1
2 p u b l i c i n t e r f a c e D i s p a t c h e r {
3 p u b l i c v o i d s t a r t D i s p a t c h i n g ( S e r v e r S o c k e t s e r v S o c k , L o g g e r l o g g e r ,
4 P r o t o c o l F a c t o r y p r o t o F a c t o r y ) ;
5 }
Di spat cher . j ava
To implement the thread-per-client dispatcher, we simply pull the for loop from main()
in T C P E c h o S e r v e r T h r e a d . java into the st art Di spat chi ng() met hod of the new dispatcher. The
only other change we need to make is to use the protocol factory instead of instantiating a
particular protocol.
Th read PerDi s patc he r .j a va
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0 i m p o r t j a v a . n e t . * ; / / f o r S o c k e t a n d S e r v e r S o c k e t
1 i m p o r t j a v a . i o . * ; / / f o r I O E x c e p t i o n
2
3 c l a s s T h r e a d P e r D i s p a t c h e r i m p l e m e n t s D i s p a t c h e r {
4
5 p u b l i c v o i d s t a r t D i s p a t c h i n g ( S e r v e r S o c k e t s e r v S o c k , L o g g e r l o g g e r ,
6 P r o t o c o l F a c t o r y p r o t o F a c t o r y ) {
/ / R u n f o r e v e r , a c c e p t i n g a n d s p a w n i n g t h r e a d s t o s e r v i c e e a c h c o n n e c t i o n
f o r ( ; ; ) {
t r y {
S o c k e t c l n t S o c k = s e r v S o c k . a c c e p t ( ) ; / / B l o c k w a i t i n g f o r c o n n e c t i o n
R u n n a b l e p r o t o c o l = p r o t o F a c t o r y . c r e a t e P r o t o c o l ( c l n t S o c k , l o g g e r ) ;
T h r e a d t h r e a d = n e w T h r e a d ( p r o t o c o l ) ;
t h r e a d . s t a r t ( ) ;
l o g g e r . w r i t e E n t r y ( " C r e a t e d a n d s t a r t e d T h r e a d = " + t h r e a d . g e t N a m e ( ) ) ;
} c a t c h ( I O E x c e p t i o n e ) {
l o g g e r . w r i t e E n t r y ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
}
}
/ * N O T R E A C H E D * /
}
}
Thr eadPer Di spat cher . j av a
[] 4.1 Multitasking 71
We demonst rat e the use of this dispatcher and protocol factory in ThreadMain. java, which
we introduce after discussing the thread-pool approach to dispatching.
4.1.5 Thread Pool
Every new t hread consumes syst em resources: spawni ng a t hread takes CPU cycles and each
t hread has i ts own data st ruct ures (e.g., stacks) t hat consume syst em memory. I n addi t i on,
the scheduling and context switching among t hreads creates extra work. As the number
of threads increases, more and more syst em resources are consumed by t hread overhead.
Eventually, the syst em is spending more time dealing with t hread management t han with
servicing connections. At that point, adding an additional t hread may actually increase client
service time.
We can avoid this probl em by limiting the total number of t hreads and reusing threads.
Instead of spawning a new t hread for each connection, the server creates a thread pool on start-
up by spawning a fixed number of threads. When a new client connection arrives at the server,
it is assigned to a t hread from the pool. When the t hread finishes with the client, it ret urns to
the pool, ready to handle anot her request. Connection request s that arrive when all t hreads in
the pool are busy are queued to be serviced by the next available thread.
Like the thread-per-client server, a thread-pool server begins by creating a ServerSocket.
Then it spawns N threads, each of which loops forever, accepting connections from the
(shared) ServerSocket instance. When multiple t hreads si mul t aneousl y call accept () on the
same ServerSocket instance, they all block until a connection is established. Then the system
selects one thread, and the Socket instance for the new connection is ret urned only in that
thread. The other t hreads remai n blocked until the next connection is established and anot her
lucky winner is chosen.
Since each t hread in the pool loops forever, processing connections one by one, a thread-
pool server is really a set of iterative servers. Unlike the thread-per-client server, a thread-pool
t hread does not terminate when it finishes with a client. Instead, it starts over again, blocking
o n a c c e p t ().
A t h r e a d p o o l is s i m p l y a d i f f e r e n t m o d e l f o r d i s p a t c h i n g c o n n e c t i o n r e q u e s t s , s o all w e
r e a l l y n e e d t o d o is w r i t e a n o t h e r d i s p a t c h e r . P o o l D i s p a t c h e r . j a v a i m p l e m e n t s o u r t h r e a d - p o o l
d i s p a t c h e r . T o s e e h o w t h e t h r e a d - p o o l s e r v e r w o u l d b e i m p l e m e n t e d w i t h o u t d i s p a t c h e r s a n d
p r o t o c o l f a c t o r i e s , s e e T C P E c h o S e r v e r P o o l . j a v a o n t h e b o o k ' s W e b site.
Pool Di s pa t c he r . j a v a
i m p o r t j a v a . n e t . *;
i m p o r t j a v a . i o . * ;
/ / f o r S o c k e t a n d S e r v e r S o c k e t
/ / f o r l O E x c e p t i o n
c l a s s P o o l D i s p a t c h e r i m p l e m e n t s D i s p a t c h e r {
s t a t i c f i n a l S t r i n g N U M T H R E A D S = " 8 " ;
s t a t i c f i n a l S t r i n g T H R E A D P R O P = " T h r e a d s " ;
/ / D e f a u l t t h r e a d - p o o l s i z e
/ / N a m e o f t h r e a d p r o p e r t y
p r i v a t e i n t n u m T h r e a d s ; / / N u m b e r o f t h r e a d s i n p o o l
72 Chapter 4: Beyond the Basics m
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
31
32
33
34
35
36
37
38
39
4O
41
42
43
44
45
46
47 }
p u b l i c P o o l D i s p a t c h e r ( ) {
/ / G e t t h e n u m b e r o f t h r e a d s f r o m t h e S y s t e m p r o p e r t i e s o r t a k e t h e d e f a u l t
n u m T h r e a d s = I n t e g e r . p a r s e l n t ( S y s t e m . g e t P r o p e r t y ( T H R E A D P R O P , N U M T H R E A D S ) ) ;
}
p u b l i c v o i d s t a r t D i s p a t c h i n g ( f i n a l S e r v e r S o c k e t s e r v S o c k , f i n a l L o g g e r l o g g e r ,
f i n a l P r o t o c o l Y a c t o r y p r o t o F a c t o r y ) {
/ / C r e a t e N - I t h r e a d s , e a c h r u n n i n g a n i t e r a t i v e s e r v e r
f o r ( i n t i = O; i < ( n u m T h r e a d s - i ) ; i + + ) {
T h r e a d t h r e a d = n e w T h r e a d ( ) {
p u b l i c v o i d r u n ( ) {
d i s p a t c h L o o p ( s e r v S o c k , l o g g e r , p r o t o F a c t o r y ) ;
}
} ;
t h r e a d . s t a r t ( ) ;
l o g g e r . w r i t e E n t r y ( " C r e a t e d a n d s t a r t e d T h r e a d = " + t h r e a d . g e t N a m e ( ) ) ;
l o g g e r . w r i t e E n t r y ( " I t e r a t i v e s e r v e r s t a r t i n g i n m a i n t h r e a d " +
T h r e a d . c u r r e n t T h r e a d ( ) , g e t N a m e ( ) ) ;
/ / U s e m a i n t h r e a d a s N t h i t e r a t i v e s e r v e r
d i s p a t c h L o o p ( s e r v S o c k , l o g g e r , p r o t o F a c t o r y ) ;
/ * N O T R E A C H E D * /
p r i v a t e v o i d d i s p a t c h L o o p ( S e r v e r S o c k e t s e r v S o c k , L o g g e r l o g g e r ,
P r o t o c o l F a c t o r y p r o t o F a c t o r y ) {
/ / R u n f o r e v e r , a c c e p t i n g a n d h a n d l i n g e a c h c o n n e c t i o n
f o r ( ; ; ) {
t r y {
Socket clntSock = servSock. accept (); / / Block waiting for connection
Runnable prot ocol = prot oFact ory. creat eProt ocol (cl nt Sock, l ogger);
pr ot ocol . r un( ) ;
} catch ( l O E x c e p t i o n e ) {
l o g g e r . w r i t e E n t r y ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
}
PoolDispatcher.java
1. Pool Di spat cher ( ) : lines 10-13
The t hr ead- pool sol ut i on needs an addi t i onal piece of i nformat i on: t he numbe r of t hr eads
in t he pool. We need to provi de this i nf or mat i on to t he i nst ance bef or e t he t hr ead pool is
const r uct ed. We coul d pass t he numbe r of t hr eads to t he const ruct or, but this limits our
opt i ons because t he const r uct or i nt erface vari es by di spat cher. We use syst em pr oper t i es
[] 4.1 Multitasking ~
to specify the number of t hreads to PoolDispatcher. The call to System. getProperty()
ret urns a St ri ng containing the value of the "Threads" propert y or the default value if
the propert y is not defined. The string is t hen converted to an integer. (See the discussion
of system propert i es in the text below.)
2. st art Di spat chi ng(): lines 15-32
9 Spawn N- 1 t hr eads to execut e dispatchLoop(): lines 17-26
For each loop iteration, an instance of an anonymous class that extends Thread is cre-
ated. When the s t ar t () met hod is called, the t hread executes the run() met hod of this
anonymous class. The run() met hod simply calls dispatchLoop(), which i mpl ement s
an iterative server.
9 Execute d i s p a t c h L o o p ( ) i n the mai n thread: lines 27-30
The original calling t hread serves as the Nt h t hread of the pool.
3. dispatchLoop(): lines 34-46
9 Accept an i ncomi ng connect i on: line 39
Since there are N t hreads executing dispatchLoop(), up to N t hreads can be blocked
on servSock' s accept (), waiting for an incoming connection. The syst em ensures that
only one t hread gets a Socket for any particular connection. If no t hreads are blocked
on accept () when a client connection is established, the new connection is queued
until the next call to accept () (see Section 5.4.1).
9 Create a prot ocol i nst ance to handl e new connect i on: line 40
9 Run the prot ocol for the connect i on: line 41
9 Handle except i on f r om accept(): lines 42-44
Since t hreads are reused, the thread-pool solution only pays the overhead of t hread
creation N times, irrespective of the total number of client connections. Since we control the
maxi mum number of simultaneously executing threads, we can control scheduling overhead.
Of course, if we spawn too few threads, we can still have clients waiting a long time for
service; therefore, the size of the t hread pool should be t uned so that client connection time
is minimized.
In PoolDispatcher. java, we used syst em propert i es to specify the number of t hreads in
the pool. Here, we give a brief description of how syst em propert i es work.. The System class
contains a Propert i es instance that holds a set of externally defined propert y/ val ue pairs (e.g.,
class pat h and JVM version). We can also define our own properties. For example, we might
want to know a user' s favorite color. We could place this i nformat i on in the "user.favoritecolor"
property. The following code demonst rat es how to fetch and print out all syst em properties,
using the get Pr oper t i es( ) met hod of System, and how to find a particular propert y value,
using System.getProperty(). The second paramet er to get Propert y() specifies a value ("None"),
to be used if the propert y is not found. (See Li st Pr oper t i es. java on the book' s Web site for a
complete example.)
S y s t e m . g e t P r o p e r t i e s ( ) . l i s t ( S y s t e m . o u t ) ; / / P r i n t a l l S y s t e m p r o p e r t i e s
S y s t e m . o u t . p r i n t l n ( " \ n F a v o r i t e C o l o r : " + / / P r i n t f a v o r i t e c o l o r p r o p e r t y
S y s t e m . g e t P r o p e r t y ( " u s e r , f a v o r i t e c o l o r " , " N o n e " ) ) ;
74 Chapter 4: Beyond the Basics []
When runni ng Java programs from the command line, we simply use the -D option to set
a propert y value. For example, to set the propert y "user.favoritecolor" to "blue," we would try
% j a v a - D u s e r . f a v o r i t e c o l o r = b l u e L i s t P r o p e r t i e s
Note that propert i es are typically defined with hierarchical (general to specific) names, such as
java.class.path. For brevity' s sake, we did not use such a name, but in a product i on application
hierarchical names should be used to avoid collisions.
The main() of ThreadUain. java demonst r at es how to use either the thread-per-client or
t hread-pool server. This application takes three paramet ers: 1) the port number for the server,
2) the prot ocol name (use "Echo" for the echo protocol), and 3) the di spat cher name (use
"ThreadPer" or "Pool" for the thread-per-client and thread-pool servers, respectively). The
number of t hreads for the t hread pool defaults to 8. However, this can be changed to 4, for
example, by setting a syst em propert y using the -DThreads=4 option to the JVM.
% j a v a - D T h r e a d s = 4 T h r e a d M a i n 5 0 0 0 E c h o P o o l
N o t e t h a t y o u m u s t c o m p i l e E c h o P r o t o c o l F a c t o r y . j a v a , T h r e a d P e r D i s p a t c h e r . j a v a , a n d P o o l -
D i s p a t c h e r . j a v a e x p l i c i t l y b e f o r e r u n n i n g T h r e a d M a i n . j a v a . F a i l u r e t o d o s o w i l l r e s u l t i n a
C l a s s N o t F o u n d E x c e p t i o n . T h o s e c l a s s e s a r e n o t r e f e r e n c e d b y n a m e i n T h r e a d M a i n ( t h a t ' s t h e
i d e a !) , s o t h e y w i l l n o t b e a u t o m a t i c a l l y c o m p i l e d w i t h T h r e a d M a i n .
ThreadMain.java
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
i m p o r t j a v a . n e t . *;
i m p o r t j a v a . i o . * ;
/ / f o r S e r v e r S o c k e t
/ / f o r I O E x c e p t i o n
p u b l i c c l a s s T h r e a d M a i n {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s E x c e p t i o n {
i f ( a r g s . l e n g t h != 3) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : [ < O p t i o n a l p r o p e r t i e s > ] "
+ " < P o r t > < P r o t o c o l > < D i s p a t c h e r > " ) ;
i n t s e r v P o r t = I n t e g e r . p a r s e l n t ( a r g s [ 0 ] ) ;
S t r i n g p r o t o c o l N a m e = a r g s [ l ] ;
S t r i n g d i s p a t c h e r N a m e = a r g s [ 2 ] ;
/ / S e r v e r P o r t
/ / P r o t o c o l n a m e
/ / D i s p a t c h e r n a m e
S e r v e r S o c k e t s e r v S o c k = n e w S e r v e r S o c k e t ( s e r v P o r t ) ;
L o g g e r l o g g e r = n e w C o n s o l e L o g g e r ( ) ; / / L o g m e s s a g e s t o c o n s o l e
P r o t o c o l Y a c t o r y p r o t o F a c t o r y = ( P r o t o c o l F a c t o r y ) / / G e t p r o t o c o l f a c t o r y
C l a s s . f o r N a m e ( p r o t o c o l N a m e + " P r o t o c o l F a c t o r y " ) . n e w l n s t a n c e ( ) ;
D i s p a t c h e r d i s p a t c h e r = ( D i s p a t c h e r ) / / G e t d i s p a t c h e r
C l a s s . f o r N a m e ( d i s p a t c h e r N a m e + " D i s p a t c h e r " ) . n e w l n s t a n c e ( ) ;
m 4.2 Nonblocking I/O 75
22
23
24
25
}
}
dispatcher, startDispatching(servSock, logger, protoFactory) ;
/* NOT REACHED */
ThreadMain.java
1. Appl i cat i on set up and paramet er parsi ng: lines O-13
2. Create ser ver s ocket and logger: lines 15-16
3. Instanti ate a prot ocol factory: lines 17- 18
The prot ocol name is passed as the second parameter. We adopt the nami ng convention
of <ProtocolName>ProtocolFactory for the class name of the factory for the protocol
name <ProtocolName>. For example, if the second paramet er is "Echo," the correspondi ng
protocol factory is EchoProtocolFactory. The static met hod Class.forName() takes the
name of a class and ret urns a Class object. The newInstance() met hod of Class creates
a new instance of the class using the paramet erl ess constructor, protoFactory refers to
this new instance of the specified prot ocol factory.
4. Instanti ate a di spatcher: lines 19- 20
The dispatcher name is passed as the third parameter. We adopt the nami ng convention
of <DispatcherType>Dispatcher for the class name of the dispatcher of type <Dispatcher-
Type>. For example, if the third paramet er is "ThreadPer," the correspondi ng dispatcher
is ThreadPerDispatcher. dispatcher refers to the new instance of the specified dispatcher.
5. Start di spat chi ng cl i ents: line 22
ThreadMain. java makes it easy to use other protocols and dispatchers. The book' s Web
site contains some additional examples. For example, see TimeProtocolFactory. java for an
i mpl ement at i on of the time prot ocol where clients can get the server time by simply connecting
to the server on the time port.
See GUIThreadUain. j ava on the book' s Web site for an example of server integration with
a GUI. This application lists the currently connect ed client. You will need a protocol-specific
GUI i mpl ement at i on (see G U I E c h o P r o t o c o l F a c t o r y . java). 1 The paramet ers to this application
are the same as for ThreadMain. For this application to work, you must specify the GUI version
of the prot ocol factory on the command line (e.g., GUIEcho instead of Echo).
4.2 Nonblocking I / O
Socket I/O calls may block for several reasons. Data i nput met hods read() and recei ve() block
if data is not available. A wr i t e( ) on a TCP socket may block if there is not sufficient space to
buffer the t ransmi t t ed data. The accept () met hod of ServerSocket and the Socket const ruct or
1 Clearly, more decomposition is possible, but it is beyond the scope of this book.
7 6 Chapter 4: Beyond the Basics m
bot h block until a connection has been established (see Section 5.4). Meanwhile, long round-
trip times, high error rate connections, and slow (or deceased) servers may cause connect i on
est abl i shment to take a long time. In all of these cases, the met hod ret urns only after the request
has been satisfied. Of course, a blocking met hod call halts the execution of the application.
What about a program that has other tasks to perform while waiting for call com-
pletion (e.g., updat i ng the "busy" cursor or respondi ng to user requests)? These programs
may have no time to wait on a blocked met hod call. Or what about lost UDP datagrams? In
UDPEchoClientTimeout. java, the client sends a dat agram to the server and t hen waits to receive
a response. If a dat agram is not received before the timer expires, receive () unblocks to allow
the client to handle the dat agram loss. Here we describe the general nonblocking approaches
(where they exist) for various I/O met hods. (Note: As this book goes to press, additional non-
blocking I/O features have been proposed for version 1.4 of the JDK. Because these features
are still under development, we do not cover t hem here.)
4.2.1 accept(), read(), and receive()
For these met hods, we can set a bound on the maxi mum time (in milliseconds) to block, using
the setSoTimeout() met hod of Socket, ServerSocket, and DatagramSocket. If the specified time
elapses before the met hod returns, an InterruptedIOException is thrown. For Socket instances,
we can also use the avai l abl e( ) met hod of the socket' s InputStream to check for available data
before calling read ().
4.2.2 Connecting and Writing
The Socket const ruct or at t empt s to establish a connection to the host and port supplied as
argument s, blocking until either the connection is established or a syst em-i mposed t i meout
occurs. Unfortunately, the syst em-i mposed t i meout is long (on the order of minutes), and Java
does not provide any means of shortening it.
A wr i t e( ) call blocks until the last byte written is copied into the TCP i mpl ement at i on' s
local buffer; if the available buffer space is smaller t han the size of the write, some data must be
successfully t ransferred to the other end of the connection before the call to wr i t e( ) will ret urn
(see Section 5.1 for details). Thus, the amount of time that a wr i t e( ) may block is controlled
by the receiving application. Unfortunately, Java currently does not provide any way to cause
a wr i t e( ) to time out, nor can it be i nt errupt ed by anot her thread. Therefore, any prot ocol
that sends a large enough amount of data over a Socket instance can block for an unbounded
amount of time. (See Section 5.2 for furt her discussion on the consequences.)
4.2.3 Limiting Per-Client Time
Suppose we want to i mpl ement the Echo protocol with a limit on the amount of time taken to
service each client. That is, we define a target, TIMELIMIT, and i mpl ement the protocol in such
a way that after TIMELIMIT milliseconds, the protocol instance is terminated. One approach
II 4.2 Nonblocking I/O 77
si mpl y has t he pr ot ocol i nst ance keep t rack of t he amount of t he r emai ni ng time, and use
setSoTimeout () to ensur e t hat no r ead( ) call bl ocks for l onger t han t hat time. Unfort unat el y,
t here is no way to bound t he dur at i on of a wr i t e ( ) call, so we cannot really guar ant ee t hat t he
time limit will hold. T i m e l i m i t E c h o P r o t o c o l F a c t o r y . j ava i mpl ement s this appr oach.
TimelimitEchoProtocolFactory.java
0 import j ava. net . *;
1 import j ava. i o. *;
2 import j ava. ut i l . *;
3
4
5
6
7
8
9 }
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/ / for Socket
/ / for IOException and Input/OutputStream
/ / for ArrayList
p u b l i c c l a s s T i m e l i m i t E c h o P r o t o c o l F a c t o r y i m p l e m e n t s P r o t o c o l F a c t o r y {
p u b l i c R u n n a b l e c r e a t e P r o t o c o l ( S o c k e t c l n t S o c k , Logger logger) {
r e t u r n n e w T i m e l i m i t E c h o P r o t o c o l ( c l n t S o c k , l o g g e r ) ;
}
c l a s s T i m e l i m i t E c h o P r o t o c o l i m p l e m e n t s R u n n a b l e {
p r i v a t e s t a t i c f i n a l i n t B U F S I Z E = 32; / / S i z e ( i n b y t e s ) o f r e c e i v e b u f f e r
p r i v a t e s t a t i c f i n a l S t r i n g T I M E L I M I T = " i 0 0 0 0 " ; / / D e f a u l t t i m e l i m i t ( m s )
p r i v a t e s t a t i c f i n a l S t r i n g T I M E L I M I T P R O P = " T i m e l i m i t " ; / / T h r e a d p r o p e r t y
p r i v a t e i n t t i m e l i m i t ;
p r i v a t e S o c k e t c l n t S o c k ;
p r i v a t e L o g g e r l o g g e r ;
p u b l i c T i m e l i m i t E c h o P r o t o c o l ( S o c k e t c l n t S o c k , L o g g e r l o g g e r ) {
t h i s . c l n t S o c k = c l n t S o c k ;
t h i s . l o g g e r = l o g g e r ;
/ / Get the time l i mi t from the System propert i es or take the defaul t
t i mel i mi t = Integer.parseInt(System.getProperty(TIMELIMITPROP, TIMELIMIT));
}
p u b l i c v o i d r u n ( ) {
A r r a y L i s t e n t r y = n e w A r r a y L i s t ( ) ;
e n t r y . a d d ( " C l i e n t a d d r e s s a n d p o r t = " +
c l n t S o c k . g e t I n e t A d d r e s s ( ) . g e t H o s t A d d r e s s ( ) + " : " +
cl nt Sock. get Por t ( ) ) ;
entry. add("Thread = " + Thread' current Thread()' get Name());
t r y {
/ / Get the input and output I/O streams from socket
InputStream in = clntSock, getInputStream() ;
OutputStream out = clntSock, getOutputStream() ;
78 Chapter 4: Beyond the Basics II
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
6O
61
62
63
64
65
66
67
68
69
7O
71
}
}
i n t r e c v M s g S i z e ; / / S i z e o f r e c e i v e d m e s s a g e
i n t t o t a l B y t e s E c h o e d = O; / / B y t e s r e c e i v e d f r o m c l i e n t
b y t e [ ] e c h o B u f f e r = n e w b y t e [ B U F S I Z E ] ; / / R e c e i v e b u f f e r
l o n g e n d T i m e = S y s t e m . c u r r e n t T i m e M i l l i s ( ) + t i m e l i m i t ;
i n t t i m e B o u n d M i l l i s = t i m e l i m i t ;
c l n t S o c k , s e t S o T i m e o u t ( t i m e B o u n d M i l l i s ) ;
/ / R e c e i v e u n t i l c l i e n t c l o s e s c o n n e c t i o n , i n d i c a t e d b y - i
w h i l e ( ( t i m e B o u n d M i l l i s > O) & & / / c a t c h z e r o v a l u e s
( ( r e c v M s g S i z e = i n . r e a d ( e c h o B u f f e r ) ) != - i ) ) {
o u t . w r i t e ( e c h o B u f f e r , O, r e c v M s g S i z e ) ;
t o t a l B y t e s E c h o e d + = r e c v M s g S i z e ;
t i m e B o u n d M i l l i s = ( i n t ) ( e n d T i m e - S y s t e m . c u r r e n t T i m e M i l l i s ( ) ) ;
c l n t S o c k . s e t S o T i m e o u t ( t i m e B o u n d M i l l i s ) ;
}
e n t r y . a d d ( " C l i e n t f i n i s h e d ; e c h o e d " + t o t a l B y t e s E c h o e d + " b y t e s , " ) ;
} c a t c h ( I n t e r r u p t e d l O E x c e p t i o n d u m m y ) {
e n t r y . a d d ( " R e a d t i m e d o u t " ) ;
} c a t c h ( l O E x c e p t i o n e ) {
e n t r y , a d d ( " E x c e p t i o n = " + e , g e t M e s s a g e ( ) ) ;
}
t r y { / / C l o s e s o c k e t
c l n t S o c k . c l o s e ( ) ;
} c a t c h ( I O E x c e p t i o n e ) {
e n t r y . a d d ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
}
l o g g e r , w r i t e E n t r y ( e n t r y ) ;
TimelimitEchoProtocolFactory.java
T i m e l i m i t F , c h o P r o t o c o l F a c t o r y . j a v a cont ai ns bot h the fact ory and prot ocol i nst ance
classes. The fact ory is exactly like EchoProtocolFactory, wi t h the except i on t hat it i nst ant i at es
Ti mel i mi t EehoProt oeol i nst ead of EchoProtocol. The TimelimitEchoProtoeol class is similar to
the EchoProtocol class, except t hat it at t empt s to bound the total time an echo connect i on can
exist. The defaul t time is 10 seconds; the t ot al number of mi l l i seconds per connect i on can be
set usi ng the "Timelimit" propert y.
Anot her appr oach to limiting client service time involves st art i ng two t hr eads per client:
one t hat execut es the prot ocol and anot her t hat acts as a "watchdog, " sl eepi ng until TIMELIMIT
mi l l i seconds pass or the ot her (protocol) t hr ead finishes and i nt er r upt s it, whi chever comes
[] 4.3 Multiple Recipients 79
first. If the wat chdog awakens and the protocol t hread has not finished, the wat chdog termi-
nates the protocol thread. Unfortunately, t hreads killing other t hreads is deprecat ed in Java,
because the victim t hread' s abrupt t ermi nat i on mi ght leave some objects in an i nconsi st ent or
unrecoverable state. Since there is no other way to i nt errupt a blocking wr i t e( ) , this solution
usually will not work.
Finally, note that we could at t empt to use nonblocking I/O i nst ead of threads. Be warned,
however, that these solutions typically involve polling loops employing busy-waiting. While
adding t hreads does consume extra CPU and memor y resources, the overhead is generally
small, especially compared to that of busy-waiting.
4. 3 Mul t i pl e Reci pi ents
So far all of our sockets have dealt with communi cat i on bet ween exactly two entities, usually
a server and a client. Such one-to-one communi cat i on is somet i mes called unicast. Some
i nformat i on is of i nt erest to multiple recipients. In such cases, we could uni cast a copy of
the data to each recipient, but this may be very inefficient. Unicasting multiple copies over a
single net work connect i on wast es bandwi dt h by sending the same i nformat i on multiple times.
In fact, if we want to send data at a fixed rate, the bandwi dt h of our net work connect i on defines
a hard limit on the number of receivers we can support. For example, if our video server sends
1Mbps st reams and its net work connection is only 3Mbps (a heal t hy connect i on rate), we can
only support three si mul t aneous users.
Fortunately, net works provide a way to use bandwi dt h more efficiently. Inst ead of maki ng
the sender responsible for duplicating packets, we can give this job to the network. In our
video server example, we send a single copy of the st ream across the server' s connect i on
to the network, which t hen duplicates the data only when appropriate. With this model of
duplication, the server uses only 1Mbps across its connect i on to the network, irrespective of
the number of clients.
There are two types of one-to-many service: broadcast and multicast. With broadcast , all
host s on the (local) net work receive a copy of the message. With multicast, the message is sent
to a mul t i cast address, and the net work delivers it only to those host s that have indicated that
they want to receive messages sent to that address. In general, only UDP sockets are allowed
to broadcast or multicast.
4.3.1 Broadcast
Broadcasting UDP dat agrams is similar to uni cast i ng dat agrams, except that a broadcast ad-
dress is used i nst ead of a regular (unicast) IP address. The local broadcast address (255.255.255
.255) sends the message to every host on the same broadcast network. Local broadcast mes-
sages are never forwarded by routers. A host on an Ethernet net work can send a message to
all other host s on that same Ethernet, but the message will not be forwarded by a router. IP
also specifies directed broadcast addresses, which allow broadcast s to all host s on a specified
network; however, since most Int ernet rout ers do not forward directed broadcast s, we do not
deal with t hem here.
80 Chapter 4: Beyond the Basics []
There is no networkwide broadcast address that can be used to send a message to all
hosts. To see why, consider the impact of a broadcast to every host on the Internet. Sending
a single dat agram woul d result in a very, very large number of packet duplications by the
routers, and bandwi dt h would be consumed on each and every network. The consequences of
misuse (malicious or accidental) are too great, so the designers of IP left such an Internetwide
broadcast facility out on purpose.
Even so, local broadcast can be very useful. Often, it is used in state exchange for net work
games where the players are all on the same local (broadcast) network. In Java, the code for
unicasting and broadcast i ng is the same. To play with broadcast i ng applications, simply run
SendUDP. java using a broadcast dest i nat i on address. Run RecvUDP. java as you did before (except
that you can run several receivers at one time). Caveat: Some operating systems do not give
regular users permi ssi on to broadcast, in which case this will not work.
4. 3. 2 Multicast
As with broadcast, the mai n difference bet ween multicast and unicast is the form of the
address. A multicast address identifies a set of receivers. The designers of IP allocated a range
of the address space (from 224.0.0.0 to 239.255.255.255) dedicated to multicast. With the
exception of a few reserved multicast addresses, a sender can send dat agrams addressed
to any address in this range. In Java, multicast applications generally communi cat e using
an instance of MulticastSocket, a subclass of DatagramSocket. It is i mport ant to under st and
that a MulticastSocket is actually a UDP socket (DatagramSocket), with some extra multicast-
specific at t ri but es that can be controlled. Our next example i mpl ement s the multicast version
of SendUDP. java (see page 57).
SendUDPMul t i cast . c
0 import j ava. net . *; / / for MulticastSocket, DatagramPacket, and InetAddress
1 import j ava. i o. *; / / for 10Exception
2
3 public class SendUDPMulticast {
4
5
6
7
8
9
10
11
12
13
14
15
p u b l i c s t a t i c v o i d m a i n ( S t r i n g a r g s [ ] ) t h r o w s E x c e p t i o n {
i f ( ( a r g s . l e n g t h < 2) II ( a r g s . l e n g t h > 3) ) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n (
" P a r a m e t e r ( s ) : < M u l t i c a s t A d d r > < P o r t > [ <T T L >] " ) ;
I n e t A d d r e s s d e s t A d d r = I n e t A d d r e s s . g e t B y N a m e ( a r g s [ 0 ] ) ; / / D e s t i n a t i o n a d d r e s s
i f ( ! d e s t A d d r . i s M u l t i c a s t A d d r e s s ( ) ) / / T e s t i f m u l t i c a s t a d d r e s s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " N o t a m u l t i c a s t a d d r e s s " ) ;
i n t d e s t P o r t = I n t e g e r . p a r s e l n t ( a r g s [ l ] ) ; / / D e s t i n a t i o n p o r t
m 4.3 Multiple Recipients 8 |
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
}
}
i n t T T L ; / / T i m e T o L i v e f o r d a t a g r a m
i f ( a r g s . l e n g t h = = 3)
T T L = I n t e g e r . p a r s e l n t ( a r g s [ 2 ] ) ;
e l s e
T T L = i ; / / D e f a u l t T T L
ItemQuote quote = n e w I t e m Q u o t e ( 1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 L , " 5 m m S u p e r W i d g e t s " ,
i 0 0 0 , 1 2 9 9 9 , t r u e , f a l s e ) ;
M u l t i c a s t S o c k e t s o c k = n e w M u l t i c a s t S o c k e t ( ) ; / / M u l t i c a s t s o c k e t t o s e n d i n g
s o c k . s e t T i m e T o L i v e ( T T L ) ; / / S e t T T L f o r a l l d a t a g r a m s
ItemQuoteEncoder encoder = new ItemQuoteEncoderText() ;
byte[] codedQuote = encoder.encode(quote) ;
/ / Text e n c o d i n g
/ / C r e a t e a n d s e n d a d a t a g r a m
D a t a g r a m P a c k e t m e s s a g e = n e w D a t a g r a m P a c k e t ( c o d e d Q u o t e , c o d e d Q u o t e . l e n g t h ,
d e s t A d d r , d e s t P o r t ) ;
s o c k . s e n d ( m e s s a g e ) ;
s o c k . c l o s e ( ) ;
SendUDPMul t i cast . c
The only significant di fferences bet ween our uni cast and mul t i cast sender s are t hat 1) we
verify t hat t he gi ven addr ess is mul t i cast , and 2) we set t he initial Ti me To Live (TTL) val ue for
the mul t i cast dat agr am. Every IP dat agr am cont ai ns a TTL, i ni t i al i zed to some defaul t val ue and
decr ement ed (usually by one) by each r out er t hat f or war ds t he packet . When t he TTL r eaches
zero, t he packet is di scarded. By set t i ng t he initial val ue of t he TTL, we limit t he di st ance a
packet can travel f r om t he sender. 2
Unlike br oadcast , net wor k mul t i cast dupl i cat es t he message only to a specific set of
receivers. This set of receivers, called a mu l t i c a s t gr oup, is i dent i fi ed by a shar ed mul t i cast
(or group) address. Receivers need some me chani s m to not i fy t he net wor k of t hei r i nt er est in
recei vi ng dat a sent to a part i cul ar mul t i cast address, so t hat t he net wor k can f or war d packet s
to t hem. This notification, called j o i n i n g a gr oup, is accompl i shed wi t h t he j oi nGroup() me t hod
of Mul t i cast Socket . Our mul t i cast recei ver j oi ns a speci fi ed group, recei ves and pr i nt s a single
mul t i cast message f r om t hat group, and exits.
2 The rules for multicast TTL are actually not quite so simple. It is not necessarily the case that a packet
with TTL = 4 can travel four hops from the sender; however, it will not travel more than four hops.
82 Chapter 4: Beyond the Basics []
RecvU DPM u I t i cas t . j ava
0 i m p o r t j a v a . n e t . * ;
1 i m p o r t j a v a . i o . * ;
2
3
4
5
6
7
8
9
l O
i i
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8 s o c k . c l o s e ( ) ;
2 9 }
3 0 }
/ / f o r M u l t i c a s t S o c k e t , D a t a g r a m P a c k e t , a n d I n e t A d d r e s s
/ / f o r l O E x c e p t i o n
p u b l i c c l a s s R e c v U D P M u l t i c a s t i m p l e m e n t s I t e m Q u o t e T e x t C o n s t {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s E x c e p t i o n {
i f ( a r g s . l e n g t h != 2) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < M u l t i c a s t A d d r > < P o r t > " ) ;
I n e t A d d r e s s a d d r e s s = I n e t A d d r e s s . g e t B y N a m e ( a r g s [ 0 ] ) ; / / M u l t i c a s t a d d r e s s
i f ( ! a d d r e s s . i s M u l t i c a s t A d d r e s s ( ) ) / / T e s t i f m u l t i c a s t a d d r e s s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " N o t a m u l t i c a s t a d d r e s s " ) ;
i n t p o r t = I n t e g e r . p a r s e l n t ( a r g s [ l ] ) ; / / M u l t i c a s t p o r t
MulticastSocket sock = new MulticastSocket(port) ; / / Multicast receiving socket
sock.joinGroup(address); / / Join the multicast group
/ / C r e a t e a n d r e c e i v e a d a t a g r a m
D a t a g r a m P a c k e t p a c k e t = n e w D a t a g r a m P a c k e t (
n e w b y t e [ M A X _ W I R E _ L E N G T H ] , M A X _ W I R E _ L E N G T H ) ;
s o c k . r e c e i v e ( p a c k e t ) ;
I t e m Q u o t e D e c o d e r d e c o d e r = n e w I t e m Q u o t e D e c o d e r T e x t ( ) ;
I t e m Q u o t e q u o t e = d e c o d e r . d e c o d e ( p a c k e t ) ;
S y s t e m . o u t . p r i n t l n ( q u o t e ) ;
/ / T e x t d e c o d i n g
RecvUDPMul t i cast . j ava
The only significant difference bet ween our mul t i cast and uni cast receiver is t hat the
mul t i cast receiver must join the mul t i cast group by supplying the desired mul t i cast address.
The book' s Web site also contains anot her example of a sender and receiver mul t i cast pair.
UultieastImageSender. java t ransmi t s a set of images (JPEG or GIF) specified on the command
line, in t hree-second intervals. Uul t i cast ImageRecei ver. java receives each image and displays
it in a window.
Multicast dat agrams can, in fact, be sent from a DatagramSoeket by simply usi ng a
mul t i cast address. You can test this by using SendUDP. java (see page 57) to send to the mul t i cast
receiver. However, a MulticastSocket has a few capabilities t hat a DatagramSocket does not,
I 4.3 Multiple Recipients 83
including 1) allowing specification of the dat agram TTL, and 2) allowing the interface t hrough
which dat agrams are sent to the group to be specified/changed (an interface is identified by its
Internet address). A multicast receiver, on the other hand, must use a MulticastSocket because
it needs the ability to join a group.
MulticastSocket is a subclass of DatagramSocket, so it provides all of the DatagramSocket
met hods. We only present met hods specific to or adapt ed for MulticastSocket.
Mul t i cast Socket
Const r uct or s
M u l t i c a s t S o c k e t O
M u l t i c a s t S o c k e t ( i n t l o c a l P o r t )
C o n s t r u c t s a d a t a g r a m s o c k e t t h a t c a n p e r f o r m s o m e a d d i t i o n a l m u l t i c a s t o p e r a t i o n s .
T h e s e c o n d f o r m o f t h e c o n s t r u c t o r s p e c i f i e s t h e l o c a l p o r t . If t h e l o c a l p o r t is n o t
s p e c i f i e d , t h e s o c k e t is b o u n d t o a n y a v a i l a b l e l o c a l p o r t .
localPort Local port. A localPort of 0 allows the const ruct or to pick
any available port.
Oper at or s
voi d joinGroup(InetAddress groupAddress)
voi d leaveGroup(InetAddress groupAddress)
Join/leave a multicast group. A socket may be a member of multiple groups simulta-
neously. Joining a group of which this socket is already a member or leaving a group
of which this socket is not a member may generate an exception.
groupAddress Multicast address identifying group
voi d send(DatagramPacket packet, byt e TTL)
Send a dat agram from this socket with the specified TTL.
packet Packet to transmit. Either the packet must specify a
dest i nat i on address or the UDP socket must have a specified
remot e address and port (see connect()).
TTL Time to live for this packet
Accessors
Inet Address get Int erface()
voi d set I nt er f ace( I net Addr ess interface)
Ret urns/ set s the interface to use for multicast operat i ons on this socket. This is
primarily used on host s with multiple interfaces. Join/leave request s and dat agrams
84 Chapter 4: Beyond the Basics II
will be sent and dat agr ams will be recei ved usi ng this interface. The defaul t mul t i cast
i nt erface is pl at f or m dependent .
interface Addr ess of one of host ' s mul t i cast i nt erfaces
i nt g e t T i m e T o L i v e 0
v o i d s e t T i m e T o L i v e ( i n t TTL)
R e t u r n s / s e t s t h e T i m e T o L i v e f o r all d a t a g r a m s s e n t o n t h i s s o c k e t . T h i s c a n b e
o v e r r i d d e n o n a p e r - d a t a g r a m b a s i s u s i n g t h e s e n d ( ) m e t h o d t h a t t a k e s t h e T T L a s
a p a r a m e t e r .
T T L T i m e T o L i v e f o r t h i s p a c k e t
The deci si on to use br oadcast or mul t i cast depends on several factors, i ncl udi ng the
net wor k l ocat i on of receivers and the knowl edge of the communi cat i ng part i es. The scope of a
br oadcast on the Int ernet is rest ri ct ed to a local br oadcast net work, placing severe rest ri ct i ons
on the l ocat i on of the br oadcast receivers. Multicast communi cat i on may include recei vers
anywhere in the net work, 3 so mul t i cast has the advant age t hat it can cover a di st ri but ed set
of receivers. The di sadvant age of IP mul t i cast is t hat receivers mus t know the addr ess of a
mul t i cast group to join. Knowledge of an addr ess is not requi red to receive broadcast . In some
cont ext s, this makes br oadcast a bet t er mechani s m t han mul t i cast for discovery. All host s can
receive br oadcast by default, so it is si mpl e to ask all host s on a single net wor k a quest i on like
"Where' s the pri nt er?"
UDP uni cast , mul t i cast , and br oadcast are all i mpl ement ed usi ng an underl yi ng UDP
socket. The semant i cs of most i mpl ement at i ons are such t hat a UDP dat agr am will be del i vered
to all socket s bound to the dest i nat i on port of the packet. That is, a DatagramSoeket or
Mul t i east Soeket i nst ance bound to a local port X (with local addr ess not specified, i.e., a wild
card), on a host wi t h addr ess Y will receive any UDP dat agr am dest i ned for port X t hat is
1) uni cast wi t h dest i nat i on addr ess Y, 2) mul t i cast to a group t hat any appl i cat i on on Y has
joined, or 3) br oadcast where it can reach host Y. A receiver can use connect () to limit the
dat agr am source addr ess and port. Also, a DatagramSoeket can specify the local uni cast address,
whi ch pr event s delivery of mul t i cast and br oadcast packet s. See UDPEehoClientTimeout. j ava
for an exampl e of dest i nat i on addr ess verification and Section 5.5 for details on dat agr am
demul t i pl exi ng.
4. 4 Socket Opti ons
The TCP/IP prot ocol devel opers spent a good deal of time t hi nki ng about the defaul t behavi ors
t hat woul d sat i sfy most applications. (If you doubt this, read RFCs 1122 and 1123, whi ch
descri be in excruci at i ng detail the r e comme nde d behavi or s- - based on years of exper i ence- -
3 At the time of writing of this book, there are severe limitations on who can receive multicast traffic on
the Internet; however, multicast availability should improve over time. Multicast should work if the sender
and receivers are on the same LAN.
[] 4.5 Closing Connections 8 5
for i mpl ement at i ons of the TCP/IP protocols. ) For most appl i cat i ons, the desi gners did a good
job; however, it is sel dom the case t hat "one size fits all" really fits all. We have al ready seen
an exampl e in our UDP echo client. By default, the r ecei ve( ) met hod of DatagramSocket bl ocks
indefinitely wai t i ng on a dat agram. In our exampl e, we change t hat behavi or by specifying a
t i meout for receives on the UDP socket usi ng setSoTimeout(). In socket parl ance, each type
of behavi or we can change is called a s ocket opt i on. In Java, the socket type (e.g., Socket,
ServerSocket, DatagramSocket, and MulticastSocket) determines the applicable socket options,
which are typically queried and controlled using accessor methods like getSoTimeout() and
setSoTimeout(). Unfortunately, the Java API allows access to only a subset of the options in
the underlying sockets API. This is at ]east partly because options tend to vary in availability
from platform to platform, and Java is all about portability. However, as the versions wear
on, access to more and more socket options is being added in Java. Check the latest official
documentation for the various socket types to see the available options.
4. 5 Cl osi ng Connecti ons
You' ve probabl y never given much t hought to who closes a connect i on. In phone conversat i ons,
either side can st art the pr ocess of t er mi nat i ng the call. It typically goes somet hi ng like this:
"Well, I guess I' d bet t er go."
"OK. Bye."
"Bye."
Net work prot ocol s, on the ot her hand, are typically very specific about who "closes" first.
In the echo protocol, Figure 4.1(a), the server dutifully echoes everyt hi ng the client sends. When
the client is finished, it calls cl ose( ) . After the server has recei ved and echoed all of the dat a
sent before the client' s call to cl ose( ) , its read oper at i on r et ur ns a -1, i ndi cat i ng t hat the client
is finished. The server t hen calls cl ose ( ) on its socket. The close is a critical part of the prot ocol
because wi t hout it the server doesn' t know when the client is fi ni shed sendi ng charact ers to
echo. In HTTP, Figure 4.1(b), it' s the server t hat initiates the connect i on close. Here, the client
sends a r equest ("GET") tO the server, and the server r esponds by sendi ng a header (normal l y
"To Be . . . . Get/Guide.html ..."
"To Be . . . . 200 OK ...
"Or Not To Be" <HTML> ...
"Or Not To Be" ... </HTML>"
Closed Closed
Closed Closed
(a) (b)
Figure 4.1: Echo (a) and HTTP (b) protocol termination.
86 Chapter 4: Beyond the Basics m
st art i ng with "200 OK"), followed by the request ed file. Since the client does not know the size
of the file, the server must indicate the end-of-file by closing the socket.
Calling cl ose() on a Socket t ermi nat es bot h directions (input and output) of dat a flow.
(Subsection 5.4.2 provides a more detailed descri pt i on of TCP connect i on termination. ) Once an
endpoi nt (client or server) closes the socket, it can no longer send or r e c e i v e data. This means
t hat cl ose() can only be used to signal the other end when the caller is compl et el y finished
communi cat i ng. In the echo protocol, once the server receives the close from the client, it
i mmedi at el y closes. In effect, the client close indicates t hat the communi cat i on is compl et ed.
HTTP works the same way, except t hat the server is the t ermi nat or.
Let' s consider a different protocol. Suppose you want a compressi on server t hat takes a
st r eam of bytes, compresses them, and sends the compressed st ream back to the client. Which
endpoi nt shoul d close the connection? Since the st ream of bytes from the client is arbitrarily
long, the client needs to close the connect i on so t hat the server knows when the st r eam of
byt es to be compressed ends. When shoul d the client call cl ose()? If the client calls cl ose() on
the socket i mmedi at el y after it sends the last byte of data, it will not be able to receive the last
byt es of compressed data. Perhaps the client could wait until it receives all of the compr essed
dat a before it closes, as the echo protocol does. Unfortunately, nei t her the server nor the client
knows how many byt es to expect, so this will not work either. What is needed is a way to tell
the other end of the connect i on "I am t hrough sending," wi t hout losing the ability to receive.
Fortunately, sockets provide a way to do this. The shutdownTnput () and shutdown0utput ()
met hods of Socket allow the I/O st reams to be closed i ndependent l y. After shutdownlnput(),
the socket' s i nput st ream can no longer be used. Any undel i vered dat a is silently discarded,
and any at t empt to read from the socket' s i nput st ream will ret urn -1. After shutdown0utput ()
is called on a Socket, no more data may be sent on the socket' s out put stream. At t empt s to
write to the st ream t hrow an IOException. Any dat a wri t t en before the call to shutdown0utput ()
may be read by the remot e socket. After this, a read on the i nput st ream of the remot e socket
will ret urn -1. An application calling shutdown0utput() can continue to read from the socket
and, similarly, dat a can be wri t t en after calling shutdownInput ().
In the compressi on protocol (see Figure 4.2), the client writes the bytes to be compressed,
closing the out put st ream using shutdown0utput() when finished sending, and reads the
compr essed byte st ream from the server. The server repeat edl y reads the uncompr essed dat a
<Uncompressed ~
<Compressed bytes>
Closed
Figure 4.2: Compression protocol termination.
m 4.5 Closing Connections 87
and wri t es the compr essed dat a until the client per f or ms a shut down, causi ng the server read
to r et ur n -1, i ndi cat i ng an end-of-st ream. The server t hen closes the connect i on and exits.
After the client calls shutdown0utput (), it needs to read any r emai ni ng compr essed byt es f r om
the server.
Our compr essi on client, CompressClient. java, i mpl ement s the client side of the compres-
sion protocol. The uncompr es s ed byt es are read f r om the file specified on the command line,
and the compr essed byt es are wri t t en to a new file. If the uncompr es s ed filename is "data", the
compr essed fi l ename is "dat a. gz". Note t hat this i mpl ement at i on works for small files, but t hat
t here is a flaw t hat causes deadl ock for large files. (We di scuss and correct this shor t comi ng
in Section 5.2.)
CompressClient.java
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3O
31
0 i m p o r t j a v a . n e t . * ; / / f o r S o c k e t
1 i m p o r t j a v a . i o . * ; / / f o r l O E x c e p t i o n a n d [ F i l e ] I n p u t / 0 u t p u t S t r e a m
2
3 p u b l i c c l a s s C o m p r e s s C l i e n t {
4
p u b l i c s t a t i c f i n a l i n t B U F S I Z E = 2 5 6 ; / / S i z e o f r e a d b u f f e r
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s 1 0 E x c e p t i o n {
i f ( a r g s . l e n g t h != 3) / / T e s t f o r c o r r e c t # o f a r g s
t h r o w n e w l l l e g a l A r g u m e n t E x c e p t i o n ( " P a r a m e t e r ( s ) : < S e r v e r > < P o r t > < F i l e > " ) ;
String server = args [0] ;
i nt port = I nt eger . par sel nt ( ar gs[ 1] ) ;
String filename = args[2];
/ / S e r v e r n a m e o r I P a d d r e s s
/ / S e r v e r p o r t
/ / F i l e t o r e a d d a t a f r o m
/ / O p e n i n p u t a n d o u t p u t f i l e ( n a m e d i n p u t . g z )
F i l e l n p u t S t r e a m f i l e l n = n e w F i l e l n p u t S t r e a m ( f i l e n a m e ) ;
F i l e O u t p u t S t r e a m f i l e O u t = n e w F i l e O u t p u t S t r e a m ( f i l e n a m e + " .gz");
/ / C r e a t e s o c k e t c o n n e c t e d t o s e r v e r o n s p e c i f i e d p o r t
S o c k e t s o c k = n e w S o c k e t ( s e r v e r , p o r t ) ;
/ / S e n d u n c o m p r e s s e d b y t e s t r e a m t o s e r v e r
s e n d B y t e s ( s o c k , f i l e l n ) ;
/ / R e c e i v e c o m p r e s s e d b y t e s t r e a m f r o m s e r v e r
I n p u t S t r e a m s o c k I n = s o c k . g e t I n p u t S t r e a m ( ) ;
i n t b y t e s R e a d ; / / N u m b e r o f b y t e s r e a d
b y t e [ ] b u f f e r = n e w b y t e [ B U F S I Z E ] ; / / B y t e b u f f e r
w h i l e ( ( b y t e s R e a d = s o c k I n . r e a d ( b u f f e r ) ) != - i ) {
f i l e O u t . w r i t e ( b u f f e r , O, b y t e s R e a d ) ;
88 Chapter 4: Beyond the Basics []
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
5O
51
52
S y s t e m . o u t . p r i n t ( " R " ) ;
}
S y s t e m . o u t . p r i n t l n ( ) ;
/ / R e a d i n g p r o g r e s s i n d i c a t o r
/ / E n d p r o g r e s s i n d i c a t o r l i n e
s o c k . c l o s e ( ) ;
f i l e l n . c l o s e ( ) ;
f i l e O u t . c l o s e ( ) ;
/ / C l o s e t h e s o c k e t a n d i t s s t r e a m s
/ / C l o s e f i l e s t r e a m s
p r i v a t e s t a t i c v o i d s e n d B y t e s ( S o c k e t s o c k , I n p u t S t r e a m f i l e I n )
t h r o w s I O E x c e p t i o n {
O u t p u t S t r e a m s o c k O u t = s o c k . g e t O u t p u t S t r e a m ( ) ;
i n t b y t e s R e a d ; / / N u m b e r o f b y t e s r e a d
b y t e [ ] b u f f e r = n e w b y t e [ B U Y S I Z E ] ; / / B y t e b u f f e r
w h i l e ( ( b y t e s R e a d = f i l e I n . r e a d ( b u f f e r ) ) != - 1 ) {
s o c k O u t . w r i t e ( b u f f e r , O , b y t e s R e a d ) ;
S y s t e m . o u t . p r i n t ( " W " ) ; / / W r i t i n g p r o g r e s s i n d i c a t o r
}
s o c k . s h u t d o w n O u t p u t ( ) ; / / F i n i s h e d s e n d i n g
}
CompressClient.java
1. Appl i cat i on set up and par amet er parsing: lines 0-14
2. Create socket and open files: lines 16-21
3. Invoke sendBytes() to t r ansmi t byt es: lines 23-24
4. Receive the compr essed dat a stream: lines 26-34
The while loop receives the compressed data st ream and writes the bytes to the out put
file until an end-of-stream is signaled by a -1 from read ().
5. Close socket and file st reams: lines 36-38
6. sendBytes(): lines 41-51
Given a socket connected to a compressi on server and the file i nput stream, read all of
the uncompr essed bytes from the file and write t hem to the socket out put stream.
9 Get socket out put stream: line 43
9 Send uncompr e s s e d byt es to compr essi on server: lines 44-49
The while loop reads from the i nput st ream (in this case from a file) and repeats the
bytes to the socket out put st ream until end-of-file, indicated by -1 from read(). Each
write is indicated by a "W" pri nt ed to the console.
m 4.5 Closing Connections 8 9
9 Shut do wn t he s oc ke t out put stream: line 50
After reading and sending all of the bytes from the input file, shut down the out put
stream, notifying the server that the client is finished sending. The close will cause a
-1 ret urn from read() on the server.
To i mpl ement the compressi on server, we simply write a protocol and factory for our
threaded server architecture. Our protocol implementation, CompressProtocolFactory.java,
i mpl ement s the server-side compressi on protocol using the GZIP compressi on algorithm. The
server receives the uncompressed bytes from the client and writes t hem to a GZIP0utputStream,
which wraps the socket' s out put stream.
C om pr es s Pr ot oc ol F a c t o r y . j a v a
0 i m p o r t j a v a . n e t . * ;
1 i m p o r t j a v a . i o . * ;
2 i m p o r t j a v a . u t i l . * ;
3 i m p o r t j a v a . u t i l . z i p . * ;
4
5
6
7
8
9
l O
l l
1 2
1 3
1 4
1 5 }
1 6
1 7
1 8
1 9
2 O
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 0
3 1
/ / f o r S o c k e t
/ / f o r l O B x c e p t i o n a n d I n p u t / O u t p u t S t r e a m
/ / f o r A r r a y L i s t
/ / f o r G Z I P O u t p u t S t r e a m
p u b l i c c l a s s C o m p r e s s P r o t o c o l F a c t o r y i m p l e m e n t s P r o t o c o l F a c t o r y {
p u b l i c s t a t i c f i n a l i n t B U F S I Z E = 1 0 2 4 ; / / S i z e o f r e c e i v e b u f f e r
p u b l i c R u n n a b l e c r e a t e P r o t o c o l ( f i n a l S o c k e t c l n t S o c k , f i n a l L o g g e r l o g g e r ) {
r e t u r n n e w R u n n a b l e ( ) {
p u b l i c v o i d r u n ( ) {
C o m p r e s s P r o t o c o l F a c t o r y . h a n d l e C l i e n t ( c l n t S o c k , l o g g e r ) ;
}
} ;
p u b l i c s t a t i c v o i d h a n d l e C l i e n t ( S o c k e t c l n t S o c k , L o g g e r l o g g e r ) {
A r r a y L i s t e n t r y = n e w A r r a y L i s t ( ) ;
e n t r y . a d d ( " C l i e n t a d d r e s s a n d p o r t = " +
c l n t S o c k . g e t l n e t A d d r e s s ( ) . g e t H o s t A d d r e s s ( ) + " : " +
c l n t S o c k . g e t P o r t ( ) ) ;
e n t r y . a d d ( " T h r e a d = " + T h r e a d . c u r r e n t T h r e a d ( ) . g e t N a m e ( ) ) ;
t r y {
/ / G e t t h e i n p u t a n d o u t p u t s t r e a m s f r o m s o c k e t
I n p u t S t r e a m i n = c l n t S o c k , g e t I n p u t S t r e a m ( ) ;
G Z I P O u t p u t S t r e a m o u t = n e w G Z I P O u t p u t S t r e a m ( c l n t S o c k . g e t O u t p u t S t r e a m ( ) ) ;
b y t e [ ] b u f f e r = n e w b y t e [ B U F S I Z E ] ; / / A l l o c a t e r e a d / w r i t e b u f f e r
i n t b y t e s R e a d ; / / N u m b e r o f b y t e s r e a d
/ / R e c e i v e u n t i l c l i e n t c l o s e s c o n n e c t i o n , i n d i c a t e d b y - i r e t u r n
90 Chapter 4: Beyond the Basics II
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 }
w h i l e ( ( b y t e s R e a d = i n . r e a d ( b u f f e r ) ) != - i )
o u t . w r i t e ( b u f f e r , O, b y t e s R e a d ) ;
o u t . f i n i s h ( ) ; / / F l u s h b y t e s f r o m G Z I P O u t p u t S t r e a m
} c a t c h ( l O E x c e p t i o n e ) {
l o g g e r . w r i t e E n t r y ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
t r y { / / C l o s e s o c k e t
c l n t S o c k . c l o s e ( ) ;
} c a t c h ( l O E x c e p t i o n e ) {
e n t r y , a d d ( " E x c e p t i o n = " + e . g e t M e s s a g e ( ) ) ;
l o g g e r , w r i t e E n t r y ( e n t r y ) ;
CompressProtocolFactory.java
1. Fact or y me t hod for compr essi on prot ocol : lines 9-15
cr eat ePr ot ocol ( ) ret urns an anonymous class instance t hat i mpl ement s the Runnable
interface. The run() met hod of this instance simply calls the static met hod CompressPro-
t ocol Fact or y. handl eCl i ent ( ) , which i mpl ement s the server-side compressi on protocol.
Note t hat we do n o t need a separat e CompressProtocol class, because cr eat ePr ot ocol ( )
ret urns the type of instance (one t hat i mpl ement s Runnable) t hat we need.
2. handl eCl i ent (): lines 17-38
Given a socket connect ed to the compressi on client, read the uncompr essed byt es from
the client and write the compressed bytes back.
9 Get socket I/ O st reams: lines 26-27
The socket' s out put st ream is wrapped in a GZlP0utputStream. The sequence of byt es
wri t t en to this st ream is compressed, using the GZIP algorithm, before being wri t t en
to the underl yi ng out put stream.
9 Read uncompr e s s e d and wri t e compr es s ed byt es: lines 29-33
The while loop reads from the socket i nput st ream and writes to the GZlP0utputStream,
which in t urn writes to the socket out put stream, until the end-of-st ream indication is
received.
9 Fl ush and close: lines 35-44
Calling f i ni s h( ) on the GZlP0utputStream is necessary to flush any bytes t hat may be
buffered by the compressi on algorithm.
A simple iterative version of the server can be found in C o m p r e s s S e r v e r . java on the book' s
Web site.
n 4.8 Exercises 91
4. 6 Appl et s
Applets can perform net work communi cat i on using TCP/IP sockets, but there are severe
restrictions on how and with whom they can converse. Without such restrictions, unsuspect i ng
Web browsers might execute malicious applets that could, for example, send fake email,
at t empt to hack other systems while the browser user gets the blame, and so on. These security
restrictions are enforced by the Java security manager, and violations by the applet result in
a SecurityException. Typically, browsers only allow applets to communi cat e with the host
that served the applet. This means that applets are usually restricted to communi cat i ng with
applications executing on that host, usually a Web server originating the applet. The list of
security restrictions and general applet programmi ng is beyond the scope of this book. It is
wort h noting, however, that the default security restrictions can be altered, if allowed by the
browser user.
Suppose that you want ed to i mpl ement an applet that allowed users to type and save notes
to themselves on their browser. Browser security restrictions prevent applets from saving data
directly on the local file system, so you would need some other means besides local disk I/O
to save the notes. Fi l eCl i ent Appl et . java (available from the book' s Web site) is an applet that
allows the user to type text into an editor window and, by clicking the "Save" but t on, copy the
text over the net work to a server (running on port 5000). The server, YCPFileServer. java (also
on the book' s Web site), saves the data to a file. It takes a port (use 5000 to work with the applet)
and the name of the file. The server must execute on the Web server that serves the applet to
the browser. Note that there is not hi ng applet specific about the server. Fi l eCl i ent Appl et .html
on the Web site demonst rat es how to integrate the applet into a Web page. Be warned that the
applet is based on Swing, and most browsers don' t have the Swing library. The HTML file should
downl oad the necessary file to make this work, but it is not guaranteed.
4. 7 Wrappi ng Up
We have di scussed some of the ways Java provides access to advanced features of the sockets
API, and how built-in features such as t hreads can be used with socket programs. In addition
to these facilities, Java provides several mechani sms that operate on top of TCP or UDP and
at t empt to hide the complexity of prot ocol development. For example, Java Remote Method
Invocation (RMI) allows Java objects on different host s to invoke one anot her' s met hods as
if the objects all reside locally. The URL class and associated classes provide a framework
for developing Web-related programs. Many other st andard Java library mechani sms exist,
providing an amazi ng range of services. These mechani sms are beyond the scope of this book;
however, we encourage you to look at the book' s Web site for descriptions and code examples
for some of these libraries.
4. 8 Exercises
1. State precisely the conditions under which an iterative server is preferable to a multipro-
cessing server.
~ Chapter 4: Beyond the Basics III
2. Would you ever need to i mpl ement a t i meout in a client or server t hat uses TCP?
3. How can you det er mi ne the mi ni mum and maxi mum allowable sizes for a socket ' s send
and receive buffers? Det ermi ne the mi ni mums for your syst em.
4. Write an iterative di spat cher usi ng the di spat chi ng f r amewor k f r om this chapt er.
5. Write the server side of a r andom- number server usi ng the prot ocol fact ory f r amewor k
f r om this chapt er. The client will connect and send the upper bound, B, on the r andom
number to the server. The server shoul d r et ur n a r andom number bet ween 1 and B,
inclusive. All number s shoul d be specified in bi nary f or mat as 4-byte, t wo' s- compl ement ,
bi g-endi an integers.
6. Modify TCPEehoClient. java so t hat it closes its out put side of the connect i on before
at t empt i ng to receive any echoed data.
chapt er 5
Under the. Hood
So me of the subt l et i es of net wor k pr ogr ammi ng are difficult to grasp wi t hout some
under st andi ng of the dat a st r uct ur es associ at ed wi t h the socket i mpl ement at i on and cert ai n
details of how the underl yi ng prot ocol s work. This is especially t rue of TCP socket s (i.e.,
i nst ances of Socket). This chapt er descri bes some of what goes on under the hood when you
create and use an i nst ance of Socket or ServerSocket. (The initial di scussi on and Section 5.5
appl y as well to DatagramSocket and Uul t i east Socket . However, mos t of this chapt er focuses
on TCP sockets, t hat is, Socket and ServerSocket.) Please not e t hat this descri pt i on covers only
the nor mal sequence of event s and gl osses over many details. Nevertheless, we believe t hat
even this basic level of under st andi ng is helpful. Readers who want the full st ory are referred
to the TCP specification [13] or to one of the mor e compr ehensi ve t reat i ses on the subj ect [3,
22].
Figure 5.1 is a simplified view of some of the i nf or mat i on associ at ed wi t h a Socket
i nst ance. The classes are suppor t ed by an underl yi ng i mpl ement at i on t hat is provi ded by
the JVM and/ or the pl at f or m on whi ch it is r unni ng (i.e., the "socket layer" of the host ' s OS).
Operat i ons on the Java obj ect s are t r ansl at ed into mani pul at i ons of this underl yi ng abst ract i on.
In this chapt er, "Socket" refers generically to one of the classes in Figure 5.1, while "socket"
refers to the underl yi ng abst ract i on, whet her it is provi ded by an underl yi ng OS or the JVM
i mpl ement at i on itself (e.g., in an embedded system). It is i mpor t ant to not e t hat ot her (possibly
non-Java) pr ogr ams r unni ng on the same host may be usi ng the net wor k via the underl yi ng
socket abst ract i on, and t hus compet i ng wi t h Java Socket i nst ances for resources such as port s.
By "socket st ruct ure" here we mean the collection of dat a st r uct ur es in the underl yi ng
i mpl ement at i on (of bot h the JVM and TCP/IP, but pri mari l y the latter) t hat cont ai n the i nforma-
tion associ at ed wi t h a part i cul ar Socket i nst ance. For example, the socket st ruct ure contains,
among ot her i nf or mat i on
9 The local and r emot e Int ernet addr esses and por t number s associ at ed wi t h the socket.
The local Int ernet addr ess (labeled "Local IP" in the figure) is one of t hose assi gned to
the local host; the local port is set at Socket creat i on time. The r emot e addr ess and port
i dent i fy the r emot e socket, if any, to whi ch the local socket is connect ed. We will say more
93
9 4 Chapter 5: Under the Hood II
o
o
q2
C~
<
o
cu
+ ~
4-J
~iD 4-J
H O
Socket, DatagramSocket, MulticastSocket,
or S e r v e r S ock e t instance
SendQ [
I RecvQ
To network
Closed
Local port
Local IP
Remote port
Remote IP
Underlying socket structure
Fi gur e 5. 1: Data structures associated with a socket.
about how and when these values are det er mi ned short l y (Section 5.5 cont ai ns a concise
summary).
9 A FIFO queue of received dat a waiting to be delivered and a queue for dat a waiting to be
t ransmi t t ed.
9 For a TCP socket, addi t i onal prot ocol state i nformat i on relevant to the openi ng and
closing TCP handshakes. In Figure 5.1, the state is "Closed"; all sockets st art out in the
Closed state.
Knowing t hat t hese dat a st ruct ures exist and how they are affected by the underl yi ng
prot ocol s is useful because t hey cont rol vari ous aspect s of the behavi or of the vari ous Socket
objects. For example, because TCP provi des a rel i abl e byt e-st ream service, a copy of any dat a
wr i t t en to a Socket' s 0utputStream must be kept until it has been successfully received at the
ot her end of the connection. Writing dat a to the out put st r eam does n o t i mpl y t hat the dat a has
actually been sent - - onl y t hat it has been copied into the local buffer. Even f l ush( ) i ng a Socket' s
0utputStream doesn' t guarant ee t hat anyt hi ng goes over the wire immediately. Moreover, the
nat ure of the byt e-st ream service means t hat message boundar i es are n o t preserved in the
i nput st ream. As we saw in Section 3.3, this compl i cat es the process of receiving and parsi ng
for some prot ocol s. On the ot her hand, wi t h a DatagramSoeket, packet s are n o t buffered for
ret ransmi ssi on, and by the time a call to the send () met hod ret urns, the dat a has been given to
[] 5.1 Buffering and TCP 95
the net wor k subsyst em for t ransmi ssi on. If the net wor k subsyst em cannot handl e the message
for some reason, the packet is silently dr opped (but this is rare).
The next t hree sections deal wi t h some of the subtleties of sendi ng and receiving wi t h
TCP's byt e-st ream service. Then, Section 5.4 consi ders the connect i on est abl i shment and ter-
mi nat i on of the TCP protocol. Finally, Section 5.5 di scusses the process of mat chi ng i ncomi ng
packet s to sockets and the rules about bi ndi ng to port numbers.
5.1 Buffer i ng and TCP
As a pr ogr ammer , the most i mpor t ant thing to r emember when usi ng a TCP socket is this:
Yo u c a n n o t a s s ume a n y c o r r e spo n d e n c e b e t we e n wr i t e s t o t he o ut put s t r e a m a t o n e e n d
o f t he c o n n e c t i o n a n d r e a d s f r o m t he i n put s t r e a m a t t he o t he r e n d .
In particular, dat a passed in a single i nvocat i on of the out put st ream' s wr i t e( ) met hod at
the sender can be spread across mul t i pl e i nvocat i ons of the i nput st ream' s read() met hod at
the ot her end; and a single read() may r et ur n dat a passed in mul t i pl e wr i t e( ) s. To see this,
consi der a pr ogr am t hat does the following:
byt e [ ] buffe r 0 = n e w byt e [ I000 ] ;
byte[] buffe r l = n e w byte[2000];
byte[] buffe r 2 = n e w byte[S000];
,
Socket s = n e w Socket(destAddr, destPort) ;
0ut put S t r e a m out = s. g e t 0ut put S t r e a m () ;
out .write(buffer0) ;
,
out .write(bufferl) ;
out. wr it e (buffer2) ;
s.close() ;
w h e r e t he ellipses r e p r e s e n t c od e t ha t s e t s u p t he d a t a in t h e buffe r s b u t con t a in s n o ot h e r
calls to out. wr it e (). T h r o u g h o u t t his dis cus s ion , "in" r e fe r s to t h e I n p u t S t r e a m of t he receiver's
Socket, a n d "out " refers to t he 0 u t p u t S t r e a m of t he s e n de r 's Socket.
T h i s T C P c on n e c t i on t r a n s fe r s 8 0 0 0 b y t e s to t he receiver. T h e w a y t h e s e 8 0 0 0 b y t e s are
g r ou p e d for delivery at t he r e ce iv in g e n d of t he c on n e c t i on d e p e n d s o n t he t i m i n g b e t w e e n
t he ou t . w r i t e ( ) s a n d i n . r e a d ( ) s at t h e t w o e n d s of t he c on n e c t i on - - a s we l l a s t he s iz e of t he
buffe r s p r ov i d e d to t he in. r e a d ( ) calls.
9 ~ Chapter 5: Under the Hood I
Sending implementation Receiving implementation Receiving program
I I I I
SendQ
s e n d ( )
TCP protocol
RecvQ Delivered
6500 bytes 1500 bytes 0 bytes
First write (1000 bytes)
Second write (2000 bytes)
:!jiiii~ Third write (5000 bytes)
Figure 5.2: State of the three queues after three writes.
We can think of the sequence of all bytes sent (in one direction) on a TCP connection up
to a particular i nst ant in time as being divided into three FIFO queues:
1. SendQ: Bytes buffered in the underlying i mpl ement at i on at the sender that have been
written to the out put st ream but not yet successfully t ransmi t t ed to the receiving host.
2. RecvQ: Bytes buffered in the underlying i mpl ement at i on at the receiver waiting to be
delivered to the receiving pr ogr am- - t hat is, read from the input stream.
3. Delivered: Bytes already read from the input st ream by the receiver.
A call to out . wr i t e( ) at the sender appends bytes to SendQ. The TCP protocol is responsible
for moving byt es- - i n or der - - f r om Se ndQ to RecvQ. It is i mport ant to realize that this transfer
cannot be controlled or directly observed by the user program, and that it occurs in chunks
whose sizes are more or less i ndependent of the size of the buffers passed in wri t e()s. Bytes
are moved from RecvQ to Del i vered as they are read from the Socket's InputStream by the
receiving program; the size of the t ransferred chunks depends on the amount of data in RecvQ
and the size of the buffer given to read().
Figure 5.2 shows one possible state of the three queues a ft e r the three out . wr i t e( ) s in
the example above, but before any in. reads ()s at the other end. The different shading pat t erns
denote bytes passed in the three different invocations of wri t e() shown above.
Now suppose the receiver calls read() with a byte array of size 2000. The read() call
will move all of the 1500 bytes present in the waiting-for-delivery (RecvQ) queue into the byte
array and ret urn the value 1500. Note that this data includes bytes passed in bot h the first and
second calls to wri t e(). At some time later, after TCP has completed transfer of more data, the
three partitions might be in the state shown in Figure 5.3.
If the receiver now calls read () with a buffer of size 4000, that many bytes will be moved
from the waiting-for-delivery (RecvQ) queue to the already-delivered (Delivered) queue; this
includes the remaining 1500 bytes from the second wri t e(), plus the first 2500 bytes from the
third wri t e(). The resulting state of the queues is shown in Figure 5.4.
The number of bytes ret urned by the next call to read() depends on the size of the
buffer and the timing of the transfer of data over the net work from the send-side socket/TCP
II 5.2 Buffer Deadlock 97
Sending implementation
SendQ
500 bytes
Figure 5.3: After first read().
Receiving implementation Receiving program
RecvQ
m_
6000 bytes
Delivered
1500 bytes
n First write (1000 bytes)
B Second write (2000 bytes)
,i:::i~: Third write (5000 bytes)
Sending implementation
I I I
SendQ
500 bytes
Figure 5.4: After another read().
Receiving implementation
RecvQ
l
2000 bytes
Receiving program
I I
Delivered
I n
5500 bytes
n First write (1000 bytes)
Second write (2000 bytes)
,, Third write (5000 bytes)
i mpl ement at i on to the receive-side i mpl ement at i on. The movement of dat a f r om the S e n d Q to
the Re c v Q buffer has i mpor t ant i mpl i cat i ons for the design of appl i cat i on prot ocol s. We have
already encount er ed the need to parse messages as t hey are received via a Socket when in-
band delimiters are used for frami ng (see Section 3.3). In the following sections, we consi der
two more subtle ramifications.
5. 2 Buf f er De ad l o ck
Application prot ocol s have to be desi gned wi t h some care to avoid d e a d l o c k--t ha t is, a state
in whi ch each peer is bl ocked waiting for the ot her to do somet hi ng. For example, it is
pret t y obvi ous t hat if bot h client and server try to receive i mmedi at el y after a connect i on
is established, deadl ock will result. Deadlock can also occur in less i mmedi at e ways.
The buffers S e n d Q and R e c v Q in the i mpl ement at i on have limits on their capacity.
Al t hough the actual amount of memor y they use may grow and shri nk dynamically, a hard
limit is necessary to prevent all of the syst em' s memor y from being gobbl ed up by a single
9 8 Chapter 5: Under the Hood II
TCP connect i on under cont rol of a mi sbehavi ng pr ogr am. Because t hese buf f er s are finite, t hey
can fill up, and it is t hi s fact, coupl ed wi t h TCP' s fl ow cont rol mechani s m, t hat l eads to t he
possi bi l i t y of anot her f or m of deadl ock.
Once R e c v Q is full, t he TCP flow cont rol mechani s m ki cks in and pr event s t he t r ans f er of
any byt es f r om t he sendi ng host ' s SendQ, unt i l space becomes available in R e c v Q as a r esul t
of t he recei ver calling t he i nput s t r eam' s r ead( ) met hod. (The pur pos e of t he flow cont r ol
me c ha ni s m is to ensur e t hat t he sender does not t r ans mi t mor e dat a t han t he recei vi ng s ys t em
can handl e. ) A sendi ng pr ogr am can cont i nue to call send unt i l S e n d Q is full; however, once
S e n d Q is full, a call to out . wr i t e ( ) will bl ock unt i l space becomes available, t hat is, unt i l some
byt es are t r ans f er r ed to t he recei vi ng socket ' s Re c v Q. If Re c v Q is also full, ever yt hi ng st ops
unt i l t he recei vi ng pr ogr am calls i n. read () and some byt es are t r ans f er r ed to Del i vered.
Let' s as s ume t he si zes of S e n d Q and R e c v Q are SQS and RQS, respect i vel y. A wr i t e ( ) call
wi t h a byt e ar r ay of size n such t hat n > SQS will not r et ur n unt i l at l east n - SQS byt es have
been t r ans f er r ed to Re c v Q at t he recei vi ng host . If n exceeds (SQS + RQS), wr i t e ( ) cannot
r et ur n unt i l af t er t he recei vi ng pr ogr am has r ead at l east n - (SQS + RQS) byt es f r om t he
i nput st r eam. If t he recei vi ng pr ogr am does not call r ead( ) , a large send() may not compl et e
successful l y. In part i cul ar, if bot h ends of t he connect i on i nvoke t hei r r espect i ve out put
s t r eams ' wr i t e ( ) me t hod si mul t aneousl y wi t h buf f er s gr eat er t han SQS + RQS, deadl ock will
resul t : nei t her wri t e will ever compl et e, and bot h pr ogr ams will r emai n bl ocked forever.
As a concr et e exampl e, consi der a connect i on bet ween a pr ogr am on Host A and a pr ogr a m
on Host B. As s ume SQS and RQS are 500 at bot h A and B. Figure 5.5 shows what happens
when bot h pr ogr ams t ry to send 1500 byt es at t he same time. The first 500 byt es of dat a in t he
pr ogr a m at Host A have been t r ans f er r ed to t he ot her end; anot her 500 byt es have been copi ed
i nt o S e n d Q at Host A. The r emai ni ng 500 byt es cannot be s e nt - - a nd t her ef or e out . wr i t e( ) will
not r et ur n- - unt i l space frees up in R e c v Q at Host B. Unfort unat el y, t he same si t uat i on hol ds
in t he pr ogr a m at Host B. Therefore, nei t her pr ogr am' s wr i t e ( ) call will ever compl et e.
s e n d ( s , b u f f e r , 1 5 0 0 , O ) ; s e n d ( s , b u f f e r , 1 5 00, 0) ;
To be sent Se nd Q R ecvQ Delivered
Delivered RecvQ SendQ
I I I
I I I I I
To be sent
!
I I I
Program Implementation Implementation Program
I I I I
Host A Host B
Figure 5.5: Deadlock due to simultaneous wri t e()s to output streams at opposite ends of the connection.
m 5.2 Buffer Deadlock 9 9
The mo r a l o f the story: Design the protocol car eful l y to avoi d se ndi ng large quant i t i es o f
dat a si mul t a n e o usl y in both directions.
Can this really happen? Let' s review the compr essi on prot ocol exampl e in Section 4.5. Try
runni ng the compr essi on client wi t h a large file t hat is still large a ft e r compressi on. The preci se
definition of "large" here depends on your syst em, but a file t hat is al ready compr essed and
exceeds 2MB shoul d do nicely. For each r ead/ wr i t e, the compr essi on client pri nt s an "R"/"W"
to the console. If bot h the uncompr es s ed and compr essed versi ons of the file are large enough,
your client will pri nt a series of Ws and t hen st op wi t hout t er mi nat i ng or pri nt i ng any Rs.
Why does this happen? The pr ogr am CompressClient. j ava sends all of the uncompr es s ed
dat a to the compr essi on server before it at t empt s to read anyt hi ng f r om the compr essed
st ream. The server, on the ot her hand, si mpl y reads the uncompr es s ed byt e sequence and
writes the compr essed sequence back to the client. (The number of byt es the server reads before
it wri t es some compr essed dat a depends on the compr essi on al gori t hm it uses.) Consi der the
case where S e n d Q and Re c v Q for bot h client and server hol d 500 byt es each and the client
sends a 10, 000-byte (uncompressed) file. Suppose also t hat for this file the server reads about
1000 byt es and t hen wri t es 500 byt es, for a 2:1 compr essi on ratio. After the client sends 2000
bytes, the server will event ual l y have read t hem all and sent back 1000 byt es, and the client' s
Re c v Q and the server' s S e n d Q will bot h be full. After the client sends anot her 1000 byt es and
the server reads t hem, the server' s subsequent at t empt to write will block. When the client
sends the next 1000 byt es, the client' s S e n d Q and the server' s Re c v Q will bot h fill up. The next
client write will block, creat i ng deadlock.
How do we solve this probl em? The easi est sol ut i on is to execut e the client writing and
readi ng loop in separat e t hreads. One t hr ead r epeat edl y reads a buffer of uncompr es s ed byt es
f r om a file and sends t hem to the server unt i l the end of the file is reached, wher eupon it calls
shutdown0utput() on the socket. The ot her t hr ead r epeat edl y reads a buffer of compr essed
byt es f r om the server and wri t es t hem to the out put file, unt i l the i nput st r eam ends (i.e., the
server closes the socket). When one t hr ead blocks, the ot her t hr ead can pr oceed i ndependent l y.
We can easily modi f y our client to follow this appr oach by put t i ng the call to SendBytes() in
Com p r e s s Cl ie n t . j a v a inside a t h r e a d a s follows:
Thr e a d thread = n e w Thread() {
public v oid r un () {
try {
SendBytes(sock, fil e In );
} catch (Exception ig n or e d ) {}
}
};
thread.start();
S e e Com p r e s s Cl i e n t N oD e a d l oc k . j a v a on t he b ook ' s W e b site for t he c om p l e t e e x a m p l e . C a n
w e solve t his p r ob l e m w i t h ou t u s i n g t h r e a d s ? T o g u a r a n t e e d e a d l oc k a v oi d a n c e in a single
t hr eaded solution, we need nonbl ocki ng writes, whi ch are not available in the current versi on
of Java (see Section 4.2).
! OO Chapter 5: Under the Hood m
5. 3 Per f or mance I mpl i cat i ons
The TCP i mpl ement at i on' s need to copy user dat a into SendQ for pot ent i al ret ransrni ssi on
also has i mpl i cat i ons for performance. In particular, the sizes of the SendQ and RecvQ buffers
affect the t hr oughput achievable over a TCP connection. Thr oughput refers to the rate at whi ch
byt es of user dat a from the sender are made available to the receiving program; in pr ogr ams
t hat t ransfer a large amount of data, we want to maxi mi ze this rate. In the absence of net wor k
capacity or ot her limitations, bigger buffers generally resul t in higher t hr oughput .
The r eason for this has to do wi t h the cost of t ransferri ng dat a into and out of the buffers
in the underl yi ng i mpl ement at i on. If you want to t ransfer n byt es of dat a (where n is large),
it is generally much more efficient to call wr i t e( ) once wi t h a buffer of size n t han it is to
call it n t i mes wi t h a single byte. 1 However, if you call wr i t e( ) wi t h a size par amet er t hat is
much larger t han SQS, the syst em has to t ransfer the dat a from the user address space in SQS-
si zed chunks. That is, the socket i mpl ement at i on fills up the SendQ buffer, waits for dat a to
be t r ansf er r ed out of it by the TCP prot ocol , refills SendQ, waits some more, and so on. Each
time the socket i mpl ement at i on has to wait for dat a to be r emoved from SendQ, some time
is wast ed in the form of overhead (a cont ext switch occurs). This overhead is comparabl e to
t hat i ncurred by a compl et el y new call to wr i t e( ) . Thus, the effective size of a call to wr i t e( )
is l i mi t ed by the actual SQS. For readi ng from the InputStream, the same principle applies:
however large the buffer we give to read(), it will be copied out in chunks no larger t han RQS,
wi t h overhead i ncurred bet ween chunks.
If you are writing a pr ogr am for whi ch t hr oughput is an i mpor t ant per f or mance metric,
you will want to change the send and receive buffer sizes usi ng the set SendBufferSi ze()
and setR eceiveBufferSize() met hods of Socket. Al t hough there is always a syst em- i mposed
maxi mum size for each buffer, it is typically significantly larger t han the defaul t on moder n
syst ems. Remember t hat t hese consi derat i ons apply only if your pr ogr am needs to send an
amount of dat a significantly larger t han the buffer size, all at once. Note also t hat t hese fact ors
may make little difference if the pr ogr am deals wi t h some higher-level st r eam derived f r om
the Socket' s basic i nput st ream (say, by usi ng it to create an i nst ance of Fi l t er 0ut put St r eam or
Pri nt Wri t er), whi ch may per f or m its own i nt ernal buffering or add ot her overhead.
5. 4 TCP Socket Life Cycl e
When a new i nst ance of the Socket class is cr eat ed- - ei t her via one of the public const r uct or s or
by calling the accept () met hod of a ServerSocket --i t can i mmedi at el y be used for sendi ng and
receiving data. That is, when the i nst ance is ret urned, it is already connect ed to a r emot e
peer and the openi ng TCP message exchange, or handshake, has been compl et ed by the
i mpl ement at i on.
1 The same thing generally applies to reading data from the Socket's InputStream, although calling read()
with a larger buffer does not guarantee that more data will be returned.
m 5.4 TCP Socket Life Cycl e 101
<
9
OJO .~-4
>-
Call Socket (W.X.Y.Z, Q)
Blocks
Create
structure
Closed
Local port
Local IP
Remote port
Remote IP
Fi l l i n
l ocal and
remote
addr ess
Send
connecti on
request to
ser ver
Connecting
Local port P
Local IP A.B.C.D
Remote port Q
Remote IP W.X.Y.Z
Handshake
compl etes
v
Fi gure 5. 6: Cl ient-side connect i on establ i shment.
Returns instance
Established
Local port P
Local IP A.B.C.D
Remote port Q
Remote IP W.X.Y.Z
Let us t herefore consi der in more detail how the underl yi ng st ruct ure gets to and from the
connected, or "Established," state; as you' ll see later (see Section 5.4.2), t hese details affect the
definition of reliability and the ability to create a Socket or ServerSocket bound to a part i cul ar
port.
5.4.1 Connecting
The rel at i onshi p bet ween an i nvocat i on of the Socket const r uct or and the prot ocol events
associ at ed wi t h connect i on est abl i shment at the client are i l l ust rat ed in Figure 5.6. In this and
the remai ni ng figures of this section, the large arrows depict external events t hat cause the
underl yi ng socket st ruct ures to change state. Events t hat occur in the appl i cat i on pr ogr am- -
t hat is, met hod calls and r et ur ns- - ar e shown in the upper part of the figure; events such as
message arrivals are shown in the lower part of the figure. Time proceeds left to right in these
figures. The client' s Int ernet address is depi ct ed as A.B.C.D, while the server' s is W.X.Y.Z; the
server' s por t number is Q.
When the client calls the Socket const r uct or wi t h the server' s Int ernet address, W.X.Y.Z,
and port, Q, the underl yi ng i mpl ement at i on creates a socket instance; it is initially in the Closed
state. If the client did not specify the local addr es s / por t in the const r uct or call, a local port
number (P), not al ready in use by anot her TCP socket, is chosen by the i mpl ement at i on. The
local Int ernet address is also assigned; if not explicitly specified, the address of the net wor k
interface t hr ough whi ch packet s will be sent to the server is used. The i mpl ement at i on copies
the local and remot e addresses and port s into the underl yi ng socket st ruct ure, and initiates
the TCP connect i on est abl i shment handshake.
The TCP openi ng handshake is known as a 3-way handshake because it typically involves
three messages: a connect i on request from client to server, an acknowl edgment from server
to client, and anot her acknowl edgment from client back to server. The client TCP consi ders
the connect i on to be est abl i shed as soon as it receives the acknowl edgment from the server.
| 02 Chapter 5: Under the Hood III
r
L ~
~ o
<
o
.~--4
Call ServerS0cket (Q)
Create
structure
Closed
Local port
Local IP
Remote port
Remote IP
Figure 5.7: Server-side socket setup.
Fill in
l ocal port,
set state
I)
Returns instance
Listening
Local port Q
Local IP *
Remote port *
Remote IP *
In t he nor mal case, t hi s happens quickly. However, t he I nt er net is a best - ef f or t net wor k, and
ei t her t he cl i ent ' s initial mes s age or t he server' s r es pons e can get lost. For this reason, t he TCP
i mpl ement at i on r et r ans mi t s hands hake mes s ages mul t i pl e t i mes, at i ncr easi ng i nt erval s. If t he
cl i ent TCP does not receive a r es pons e f r om t he server aft er some time, it t i me s o ut and gives
up. In t hi s case t he cons t r uct or t hr ows an IOExeeption. The connect i on t i meout is general l y
long, and t hus it can t ake on t he or der of mi nut es for a Socket ( ) const r uct or to fail. If t he server
is not accept i ng connect i ons- - say, if t here is no pr ogr am associ at ed wi t h t he gi ven por t at t he
des t i nat i on- - t he server-si de TCP will send a r ej ect i on mes s age i nst ead of an acknowl edgment ,
and t he cons t r uct or will t hr ow an IOException al most i mmedi at el y.
The sequence of event s at t he server side is r at her different; we descri be it in Fi gures 5.7,
5.8, and 5.9. The server first cr eat es an i nst ance of ServerSocket associ at ed wi t h its wel l -known
por t (here, Q). The socket i mpl ement at i on cr eat es an under l yi ng socket st r uct ur e for t he new
ServerSocket i nst ance, and fills in Q as t he local por t and t he speci al wi l d c a r d a d d r e ss C*"
in t he figures) for t he local IP addr ess. (The server may also speci fy a local IP addr es s in t he
const r uct or , but t ypi cal l y it does not. In case t he server host has mor e t han one IP addr ess,
not speci fyi ng t he local addr es s allows t he socket to receive connect i ons addr es s ed to any of
t he server host ' s addr esses. ) The st at e of t he socket is set to "Listening", i ndi cat i ng t hat it is
r eady to accept i ncomi ng connect i on r eques t s addr es s ed to its port . This sequence is depi ct ed
in Figure 5.7.
The server can now call t he ServerSocket ' s accept () met hod, whi ch bl ocks unt i l t he TCP
openi ng hands hake has been compl et ed wi t h some client and a new connect i on has been
est abl i shed. We t her ef or e focus in Figure 5.8 on t he event s t hat occur in t he TCP i mpl ement at i on
when a client connect i on r eques t arrives. Note t hat ever yt hi ng depi ct ed in t hi s figure happens
"under t he covers, " in t he TCP i mpl ement at i on.
[] 5.4 TCP Socket Life Cycle 1 O3
o
Listening
Local port
Local IP
Remote port
Remote IP
I ncoming
connection
request
from
A.B.C.D/P
Listening
Local port
Local IP
Remote port
Remote IP
Q
Listening
Local port Q
Local IP *
Remote port *
Remote IP *
[ C ! e _ te_ ew_ stTytyf _ . . . . . . . . . . . . . . . . . .
and continue handshake
Connecting
Local port Q
Local IP W.X.Y.Z
Remote port P
Remote IP A.B.C.D
Handshake
completes
Established
Local port Q
Local IP W.X.Y.Z
Remote port P
Remote IP A.B.C.D
Figure 5.8: Incoming connection request processing.
When t he r eques t for a connect i on arri ves f r om t he client, a new socket s t r uct ur e is
cr eat ed for t he connect i on. The new socket ' s addr es s es are filled in ba s e d on t he arri vi ng packet :
t he packet ' s des t i nat i on I nt er net addr es s and por t (W.X.Y.Z and Q, respect i vel y) become t he
local I nt er net addr es s and port ; t he packet ' s sour ce addr es s and por t (A.B.C.D and P) become
t he r emot e I nt er net addr es s and port . Not e t hat t he local por t numbe r of t he new socket is
al ways t he same as t hat of t he ServerSocket . The new socket ' s st at e is set to "Connect i ng",
and it is a dde d to a list of not - qui t e- connect ed socket s as s oci at ed wi t h t he socket s t r uct ur e of
t he ServerSocket . Not e t hat t he Ser ver Socket i t sel f does not change st at e, nor does any of its
addr es s i nf or mat i on change.
In addi t i on to cr eat i ng a new under l yi ng socket st r uct ur e, t he ser ver - si de TCP i mpl emen-
t at i on sends an acknowl edgi ng TCP ha nds ha ke mes s age back to t he client. However, t he ser ver
TCP does not consi der t he ha nds ha ke compl et e unt i l t he t hi r d mes s age of t he 3-way ha nds ha ke
is r ecei ved f r om t he client. When t hat mes s age event ual l y arrives, t he new s t r uct ur e' s st at e is
set to "Est abl i shed", and it is t hen (and onl y t hen) move d to a list of socket s t r uct ur es asso-
ci at ed wi t h t he Ser ver Socket st r uct ur e, whi ch r e pr e s e nt es t abl i s hed connect i ons r eady to be
accept ( ) e d via t he ServerSoeket . (If t he t hi r d ha nds ha ke mes s age fails to arrive, event ual l y t he
"Connect i ng" s t r uct ur e is del et ed. )
104 Chapter 5: Under the Hood II
4-a
e~
<
o
4-a
Call accept ()
Blocks until new
connection is established
Returns Socket instance
for this structure
Listening
Local port Q
Local IP *
Remote port *
Remote IP *
Events of
Figure 5.8
Listening
Local port Q
Local IP *
Remote port *
Remote IP *
Established
Local port Q
Local IP W.X.Y.Z
Remote port P
Remote IP A.B.C.D
/
Listening
Local port Q
Local IP *
Remote port *
Remote IP *
Figure 5.9: accept () processing.
Now we can cons i der (in Fi gure 5.9) what ha ppe ns whe n t he ser ver p r o g r a m calls t he
Ser ver Soeket ' s accept () me t hod. The call unbl ocks as s oon as t her e is s ome t hi ng i n its associ -
at ed list of socket s t r uct ur es for new connect i ons . (Note t hat t hi s list ma y al r eady be non- e mpt y
whe n accept () is called.) At t hat t i me, one of t he new connect i on s t r uct ur es is r e move d f r om
t he list, and an i ns t ance of Socket is cr eat ed for it and r e t ur ne d as t he r es ul t of t he accept ().
It is i mpor t a nt t o not e t hat each s t r uct ur e i n t he Ser ver Socket ' s as s oci at ed list r e pr e s e nt s
a ful l y es t abl i s hed TCP connect i on wi t h a cl i ent at t he ot her end. I ndeed, t he cl i ent can s end
dat a as s oon as it r ecei ves t he s econd me s s a ge of t he openi ng h a n d s h a k e - - wh i c h ma y be l ong
bef or e t he ser ver calls accept () to get a Socket i ns t ance for it.
5.4.2 Closing aTCP Connection
TCP has a graceful close me c h a n i s m t hat al l ows appl i cat i ons to t er mi nat e a connect i on wi t hout
havi ng t o wor r y about l oss of dat a t hat mi ght still be i n t r ansi t . The me c h a n i s m is al so
de s i gne d t o al l ow dat a t r ans f er s i n each di r ect i on to be t e r mi na t e d i ndependent l y, as i n t he
II 5.4 TCP Socket Life Cycl e | O 5
Cal l cl ose( ) / shut downOut put ( )
Returns i mmedi at el y
o
Establ i shed
Local port P
Local IP A.B.C.D
Remot e port Q
Remot e IP W.X.Y.Z
Start
cl ose
handshake
Cl osi ng
Local port P
Local IP A.B.C.D
Remot e port Q
-- Remot e IP W.X.Y.Z
Figure 5. ! O: Cl osing a TCP connection first.
Cl ose
handshake
compl etes
Hal f cl osed
Local port P
Local IP A.B.C.D
Remot e port Q
Remot e IP W.X.Y.Z
Cl ose
handshake
9 " i ni ti ated by
remote
compl etes
Time-Wait
Local port P
Local IP A.B.C.D
Remot e port Q
Remot e IP W.X.Y.Z
c ompr e s s i on exampl e of Sect i on 4. 5. It works l ike this: the appl i cat i on i ndi cat es that it is
f i ni shed s endi ng data on a connect ed socket by cal l i ng c l o s e ( ) or by cal l i ng shutdown0utput ( ) .
At that poi nt, the underl yi ng TCP i mpl e me nt at i on first t ransmi t s any data remai ni ng in SendQ
( subj ect to avai l abl e space in RecvQ at the other end), and t hen s ends a cl osi ng TCP hands hake
me s s age to the other end. Thi s cl osi ng hands hake me s s age can be t hought of as an end-of -
t rans mi s s i on marker: it tel l s the recei vi ng TCP that no more byt es wil l be pl aced i n RecvQ.
(Note that the cl osi ng hands hake me s s age i t sel f is not pas s e d to the recei vi ng appl i cati on,
but that its pos i t i on i n the byt e st ream is i ndi cat ed by read( ) ret urni ng - 1. ) The cl osi ng TCP
wai ts for an ac knowl e dgme nt of its cl osi ng hands hake mes s age, whi ch i ndi cat es that al l data
sent on the connect i on made it saf el y to RecvQ. Once that ac knowl e dgme nt is recei ved, the
connect i on is "Hal f cl osed. " It is not completely cl os ed unti l a s ymmet ri c hands hake happens
in the other di rect i on- - t hat is, unti l both ends have i ndi cat ed that t hey have no more data to
send.
The cl osi ng event s equence i n TCP can happe n in two ways: ei ther one appl i cat i on cal l s
c l o s e ( ) (or shutdown0utput()) and c ompl e t e s its cl osi ng hands hake bef ore the other cal l s
c l o s e ( ) , or bot h cal l c l o s e ( ) s i mul t aneous l y, so that thei r cl osi ng hands hake me s s age s cross
in the net work. Figure 5. 10 s hows the s equence of event s i n the i mpl e me nt at i on when the
appl i cat i on i nvokes c l o s e ( ) before the other end cl oses. The cl osi ng hands hake me s s age is
sent, the state of the s ocket structure is set to "Cl osing", and the cal l returns. After thi s
poi nt, f urther reads and wri t es on the Socket are di s al l owed (they t hrow an except i on) . When
the ac knowl e dgme nt for the cl ose hands hake is recei ved, the state changes to "Hal f cl osed",
where it remai ns unti l the other end' s cl ose hands hake me s s age is recei ved. Not e that if the
remot e endpoi nt goes away whi l e the connect i on is in thi s state, the l ocal underl yi ng structure
wil l stay around i ndef i ni tel y. When the other end' s cl ose hands hake me s s age arrives, an
acknowl edgment is sent and the state is changed to "Time-Wait". Al t hough the corres pondi ng
Socket i nst ance in the appl i cat i on program may have l ong si nce vani shed, the as s oci at ed
underl yi ng st ruct ure cont i nues to exi st in the i mpl e me nt at i on for a mi nut e or more; the reas ons
for thi s are di s c us s e d on page 107.
| 06 Chapter 5: Under the Hood []
. , -. ~
. , --4
<
Call close()
Returns immediately
o
.F..~
Established
Local port
Local IP
Remote port
Remote IP
A.B.C.D
Q
W.X.Y.Z
C lose
handshake
initiated
by remote
completes
Close-Wait
Local port P
Local IP A.B.C.D
Remote port Q
Remote IP W.X.Y.Z
Figure 5.1 !: Closing after the other end closes.
Finish close handshake,
delete structure
y
Figure 5.11 shows the si mpl er sequence of event s at the endpoi nt t hat does not close first.
When the closing handshake message arrives, an acknowl edgment is sent i mmedi at el y, and the
connect i on st at e becomes "Close-Wait." At this point, we are j ust waiting for the appl i cat i on
to invoke the Socket' s cl ose( ) met hod. When it does, the final close handshake is i ni t i at ed
and the under l yi ng socket st r uct ur e is deallocated, al t hough references to its original Socket
i nst ance may per si st in the Java program.
In view of the fact t hat bot h cl ose( ) and shutdown0utput() r et ur n wi t hout wai t i ng for
the closing handshake to compl et e, you may wonder how the sender can be assur ed t hat sent
dat a has act ual l y made it to the receiving pr ogr am (i.e., to De l i v e r e d ). In fact, it is possi bl e
for an appl i cat i on to call cl ose( ) or shutdown0utput() and have it compl et e successful l y (i.e.,
not t hrow an Exception) whi l e t he r e is st i l l d a t a in S e n d Q . If ei t her end of the connect i on t hen
crashes before the dat a makes it to R e c v Q , dat a may be lost wi t hout the sendi ng appl i cat i on
knowi ng about it.
The best sol ut i on is to desi gn the appl i cat i on prot ocol so t hat the side t hat calls cl ose( )
first does so o n l y a ft e r receiving application-level assurance t hat its dat a was received. For
exampl e, when our TCPEehoClient pr ogr am receives the echoed copy of the dat a it sent, t here
shoul d be not hi ng more in t ransi t in ei t her direction, so it is safe to close the connect i on.
Java does provi de a way to modi f y the behavi or of the Socket' s cl ose( ) met hod, namel y,
the set SoLi nger() met hod, set SoLi nger() cont rol s whet her cl ose( ) waits for the closing hand-
shake to compl et e before ret urni ng. It t akes two par amet er s, a bool ean t hat i ndi cat es whet her
to wait, and an i nt eger specifying the number of seconds to wait before giving up. That is,
when a t i meout is specified via set SoLi nger(), cl ose( ) bl ocks unt i l the closing handshake is
compl et ed, or unt i l the specified amount of t i me passes. At the t i me of this writing, how-
ever, cl ose( ) provi des no i ndi cat i on t hat the closing handshake failed to compl et e, even if
the t i me limit set by set SoLi nger() expires before the closing sequence compl et es. In ot her
words, set SoLi nger() does not provi de any addi t i onal assurance to the appl i cat i on in current
i mpl ement at i ons.
m 5.5 Demultiplexing Demystified ! O7
The final subt l et y of closing a TCP connect i on revolves ar ound the need for the Time-
Wait state. The TCP specification requi res t hat when a connect i on t ermi nat es, at l east one of
the socket s per si st s in the Time-Wait st at e for a peri od of time aft er bot h closing handshakes
complete. This r equi r ement is mot i vat ed by the possi bi l i t y of messages bei ng del ayed in the
network. If bot h ends' underl yi ng st r uct ur es go away as soon as bot h closing handshakes
complete, and a n e w connect i on is i mmedi at el y est abl i shed bet ween the same pair of socket
addresses, a message f r om the previ ous connection, whi ch happened to be del ayed in the
network, could arrive j ust aft er the new connect i on is est abl i shed. Because it woul d cont ai n
the same source and dest i nat i on addresses, the old message could be mi st aken for a message
bel ongi ng to the new connection, and its dat a mi ght (incorrectly) be delivered to the application.
Unlikely t hough this scenario may be, TCP empl oys mul t i pl e mechani sms to prevent it,
including the Time-Wait state. The Time-Wait st at e ensures t hat every TCP connect i on ends
wi t h a quiet time, duri ng whi ch no dat a is sent. The quiet time is supposed to be equal to
twice the maxi mum amount of time a packet can r emai n in the net work. Thus, by the time a
connect i on goes away compl et el y (i.e., the socket st ruct ure leaves the Time-Wait st at e and is
deallocated) and clears the way for a new connect i on bet ween the same pair of addresses, no
messages f r om the old i nst ance can still be in the net work. In practice, the l engt h of the quiet
time is i mpl ement at i on dependent , because t here is no real mechani s m t hat limits how long a
packet can be del ayed by the net work. Values in use range f r om 4 mi nut es down to 30 seconds
or even shorter.
The most i mpor t ant consequence of Time-Wait is t hat as long as the underl yi ng socket
st ruct ure exists, no ot her socket is per mi t t ed to be associ at ed wi t h the same local port. In
part i cul ar, any at t empt to create a Socket i nst ance usi ng t hat por t will t hrow an TOException.
5.5 Demul t ipl exing Demyst ihed
The fact t hat di fferent socket s on the same machi ne can have the same local addr ess and
port number is implicit in the di scussi ons above. For example, on a machi ne wi t h only one
IP address, every new Socket i nst ance accept ( ) ed via a ServerSocket will have the same local
port number as the ServerSocket. Clearly the process of deciding to whi ch socket an i ncomi ng
packet shoul d be del i ver ed- - t hat is, the d e mul t i pl e xi n g pr ocess- - i nvol ves looking at more t han
j ust the packet ' s dest i nat i on addr ess and port. Ot herwi se t here coul d be ambi gui t y about whi ch
socket an i ncomi ng packet is i nt ended for. The process of mat chi ng an i ncomi ng packet to a
socket is actually the same for bot h TCP and UDP, and can be s ummar i zed by the following
points:
9 The local port in the socket st ruct ure mu s t mat ch the dest i nat i on port number in the
i ncomi ng packet.
9 Any addr ess fields in the socket st r uct ur e t hat cont ai n the wi l dcard value (*) are consid-
ered to mat ch a n y value in the cor r espondi ng field in the packet.
9 If t here is mor e t han one socket st ruct ure t hat mat ches an i ncomi ng packet for all four
addr ess fields, the one t hat mat ches usi ng the fewest wi l dcards gets the packet.
| O~ Chapter 5" Under the Hood II
Li st eni ng
Local por t
Local IP
Remot e por t
Remot e IP
99
Li st eni ng
Local por t
Local IP
Remot e por t
Remot e IP
99
10.1.2.3
Est abl i shed
Local por t
Local IP
Remot e por t
Remot e IP
0 1 2
Figure 5.12: Demul tipl exing with mul tipl e matching sockets.
99
192.168.3.2
30001
172.16.1.9
Est abl i shed
Local por t
Local IP
Remot e por t
Remot e IP
1025
10.1.2.3
25
10.5.5.8
For example, consi der a host wi t h two IP addresses, 10.1.2.3 and 192.168.3.2, and wi t h a
subset of its active TCP socket st ruct ures, as shown in Figure 5.12. The st ruct ure labeled 0 is
associ at ed wi t h a ServerSocket and has por t 99 wi t h a wi l dcard local address. Socket st ruct ure 1
is also for a ServerSocket on the same port, but wi t h the local IP address 10.1.2.3 specified (so
it will only accept connect i on request s to t hat address). Structure 2 is for a connect i on t hat
was accept ed via the ServerSocket for st ruct ure 0, and t hus has the same local por t number,
but also has its local and remot e Int ernet addresses filled in. Other sockets bel ong to ot her
active connect i ons. Now consi der a packet wi t h source IP address 172.16.1.10, source por t
56789, dest i nat i on IP address 10.1.2.3, and dest i nat i on port 99. It will be delivered to the
socket associ at ed wi t h st ruct ure 1, because t hat one mat ches wi t h the fewest wildcards.
When a pr ogr am at t empt s to create a socket wi t h a part i cul ar local port number, the
existing sockets are checked to make sure t hat no socket is already usi ng t hat local port. A
Socket () const r uct or will t hr ow an except i on if a n y socket mat ches the local por t and local IP
address (if any) specified in the const ruct or. This can cause probl ems in the following scenario:
1. A client pr ogr am creates a Socket wi t h a specific local port number, say, P, and uses it to
communi cat e wi t h a server.
2. The client closes the Socket, and the underl yi ng st ruct ure goes into the Time-Wait state.
3. The client pr ogr am t ermi nat es and is i mmedi at el y rest art ed.
If the new i ncarnat i on of the client at t empt s to use the same local port number, the Socket
const r uct or will t hrow an IOException, because of the ot her st ruct ure in the Time-Wait state.
As of this writing, the only way ar ound this is to wait until the underl yi ng st ruct ure leaves the
Time-Wait state.
So what det ermi nes the l ocal / forei gn addr ess/ por t ? For a ServerSocket, all const r uct or s
requi re the local port. The local address may be specified to the const ruct or; otherwise, the
local address is the wi l dcard (*) address. The foreign address and por t for a ServerSocket are
always wildcards. For a Socket, all const ruct ors require specification of the foreign address
and port. The local address and/ or port may be specified to the const ruct or. Otherwise, the
local address is the address of the net wor k interface t hr ough whi ch the connect i on to the
server is established, and the local port is a r andoml y selected, unused por t number great er
I 5.6 Exercises 109
t han 1023. For a Socket i nst ance r et ur ned by accept (), the local address is the dest i nat i on
address from the initial handshake message f r om the client, the local port is the local port of
the ServerSocket, and the foreign addr es s / por t is the local addr es s / por t of the client. For a
DatagramSocket, the local address and/ or port may be specified to the const ruct or. Otherwise
the local address is the wi l dcard address, and the local port is a r andoml y selected, unused
port number great er t han 1023. The foreign address and por t are initially bot h wildcards, and
remai n t hat way unl ess the connect () met hod is i nvoked to specify part i cul ar values.
5. 6 Exer ci ses
1. The TCP prot ocol is desi gned so t hat si mul t aneous connect i on at t empt s will succeed.
That is, if an appl i cat i on usi ng port P and Int ernet address W.X.Y.Z at t empt s to connect
to address A.B.C.D, port Q, at the same time as an appl i cat i on usi ng the same address
and por t tries to connect to W.X.Y.Z, por t P, t hey will end up connect ed to each other.
Can this be made to happen when the pr ogr ams use the sockets API?
2. The first exampl e of "buffer deadlock" in this chapt er involves the pr ogr ams on bot h
ends of a connect i on trying to send large messages. However, this is not necessary for
deadlock. How coul d the TCPEchoClient f r om Chapt er 2 be made to deadl ock when it
connect s to the TCPEchoServer from t hat chapter?
Bibliography
[1] Case, J. D., Fedor, M., and Schoffstall, M. L., "Simple Network Management Protocol
(SNMP)." Int ernet Request for Comment s 1157, May 1990.
[2] Comer, Douglas E., Internetworking with TCP/IP, Volume k Principles, Protocols, and
Architecture (third edition). Prentice Hall, 1995.
[3] Comer, Douglas E., and Stevens, David L., Internetworking with TCP/IP, Volume II: Design,
Implementation, and Internals (third edition). Prentice Hall, 1999.
[4] Comer, Douglas E., and Stevens, David L., Internetworking with TCP/IP, Volume III: Client-
Server Programming and Applications (BSD version, second edition). Prentice Hall, 1996.
[5] Deering, S., and Hinden, R., "Internet Protocol, Version 6 (IPv6) Specification." Int ernet
Request for Comment s 2460, December 1998.
[6] Gilligan, R., Thomson, S., Bound, J., and Stevens, W., "Basic Socket Interface Extensions
for IPv6." Int ernet Request for Comment s 2553, March 1999.
[7] Hughes, M., Shoffner, M., Hamner, D., and Bellus, U., Java Network Programming (second
edition). Manning, 1999.
[8] Int ernat i onal Organi zat i on for Standardization, Information Processing SystemsmOpen
Systems InterconnectionmSpecification of Abstract Syntax Notation One (ASN.1). Interna-
tional St andard 8824, December 1987.
[9] Mockapetris, P., "Domain Names- - Concept s and Facilities." Int ernet Request for Com-
ment s 1034, November 1987.
[10] Mockapetris, P., "Domain Names- - I mpl ement at i on and Specification." Internet Request
for Comment s 1035, November 1987.
[ 11] Peterson, L. L., and Davie, B. S., Computer Networks: A Systems Approach (second edition).
Morgan Kaufmann, 2000.
[12] Postel, J., "Internet Protocol." Int ernet Request for Comment s 791, September 1981.
I I I
| | 2 Bibliography m
[13] Postel, J., "Transmission Control Protocol." Internet Request for Comments 793, Septem-
ber 1981.
[14] Postel, J., "User Datagram Protocol." Internet Request for Comments 768, August 1980.
[15] Steedman, D., Abstract Syntax Notation One (ASN.1)--The Tutorial and Reference. Tech-
nology Appraisals, U.K., 1990.
[16] Stevens, W. R., TCP/IP Illustrated, Volume 1: The Protocols. Addison-Wesley, 1994.
[17] Stevens, W. R., UNIX Network Programming: Networking APIs: Sockets and XTI (second
edition). Prentice Hall, 1997.
[18] Sun Microsystems Incorporated, "External Data Representation Standard." Internet Re-
quest for Comments 1014, June 1987.
[19] Sun Microsystems Incorporated, "Network File System Protocol Specification." Internet
Request for Comments 1094, March 1989.
[20] Sun Microsystems Incorporated, "Network File System Protocol Version 3 Specification."
Internet Request for Comments 1813, June 1995.
[21] The Unicode Consortium, The Unicode Standard, Version 3.0. Addison-Wesley Longman,
2O0O.
[22] Wright, G. R., and Stevens, W. R., TCP/IP Illustrated, Volume 2: The Implementation.
Addison-Wesley, 1995.
Index
3-way handshakes, 101-102
accept () met hod of ServerSocket
blocking by, 75-76
connection establishment
events, 103-104
described, 21
returning Socket class, 1 8 - 1 9
in thread-per-client server, 7 0
in t h r e a d p o o l server, 71-73
a d d r e s s e s
broadcast, 7 9
connection establishment,
101
defined, 3
demultiplexing, 107-109
destination addresses, 9
dotted-quad notation, 4
IP (Internet), 9-12, 93-94
multicast, 80
socket structures, 93-94
sockets, 9-12
types of, 4
American Standard Code for
Information Exchange
(ASCII), 39
applets, 91
application protocols, 37, 42-43
applications, 5
architecture of TCP/IP net-
works, 2
big-endian byte order, 41
binary numbers, 40-42
blocking socket I/O calls, 75-79
boolean values, encoding, 47, 51
broadcast addresses, 79
broadcasting, 79-80, 84
browser applet security, 91
BufferedInputStream, 42
BufferedOutputStream, 42
buffering
closing connections, 105-
106
of datagrams, 24-25
deadlock, 97-99
FIFO queues, 96-97
flow control mechanism, 98
I/O streams, 42
memory limitations, 97-98
performance, effects on, 100
reliable service protocol,
94-97
setting size, 17
TCP and, 94-99
wri t e() met hod with, 20, 76
byte order, 41
bytes required for transmission,
39
character sets, 39
client
closing connections, 85-90
defined, 5
handshake events, 101-102
TCP, 12-18
TCPEchoClient. java, 13-15
UDP, 26-31
UDPEchoClientTimeout. java,
27-28
cl ose() met hod
closing connections, 85-90,
105-107
of DatagramSocket class, 26,
29,31
setSoLinger() method, 106
of Socket class, 15, 16
Closed state, 94, 101
Close-Wait state, 106
closing
connections, 85-90, 104-107
TCP streams, 16
UDP streams, 29
Closing state, 105
communication channels, 1
composing I/O streams, 42
CompressClient. java, 87-89
CompressClientNoDeadlock. java,
99
compression protocol
closing connections, 86-90
deadlock, 99
C o m p r e s s P r o t o c o l F a c t o r y . java,
8 9 - 9 0
concurrent servers. See
multitasking
connect () met hod UDP, 26
in DatagramSocket, 29
Connecting state, 103
connection-oriented protocols, 3
connections
Close-Wait state, 106
closing, 85-90, 104-107
Closing state, 105
Connecting state, 103
creating, 14, 18, 28-30
disconnecting, 30
dispatching, 69-75
Established state, 103
establishment events,
101-104
Half closed state, 105
memory limitations, 97-98
Time-Wait state, 105, 107
113
1 I 4 Index m
connections (continued)
write/read relationship,
95-96
ConsoleLogger. java, 66
corruption of data, UDP
treatment of, 23
creat eProt ocol (), 69
creating
TCP sockets, 13-21
UDP sockets, 26-33
datagram service, 3, 23, 24-26
datagram sockets, 6. See also
DatagramSocket class
DatagramPacket class, 24-26,
33-34, 39, 43, 46, 49
datagrams
creation, 28, 32
encoding information for,
57-58
lost, 26
maximum size, 33
multicasting, 80-84
sending, 28-29
TTL (Time To Live) values, 81,
83
DatagramSocket class
accessors/mutators, 30-31
close() method, 26, 29, 31
constructors, 29
instancing by clients, 26
methods, 29-30
MulticastSocket subclass,
80-84
recei ve() method, 24, 26, 29,
31-34, 75-76
send() method, 24, 26, 28,
31-34, 98
DataInput interface, 41
DataInputStream, 42
Data0utput interface, 41
Data0utputStream, 42
deadlocked buffers, 97-99
defaults, socket, 84-85
delimiters, 43-44, 47
Delivered, 96-97
demultiplexing algorithm,
107-109
destination addresses, 9
directed broadcast addresses,
79
disconnect () method, 30
Dispatcher. java, 69-70
dispatching, 69-75
Domain Name System (DNS), 5
dotted-quad notation, 4
echo servers
EchoProtocolYactory. java,
69-70
EchoProtocol. java, 63-65
TCP version, 13-14
UDP version, 31-32
encode() method, 49
encoding of information, 39-59
application protocols, 42-43
boolean values, 47, 51
character sets, 39-40
combined data
representation, 51-54
composing I/O streams, 42
delimiters, 43-44, 47
framing, 42-46
integer types, 40-41
serialization capabilities,
58-59
TCP implementation, 55- 57
text data, 39-40, 47-51
UDP socket implementation,
57-58
end-of-message markers, 43
end-of-stream, 22, 43, 45, 46,
59, 87
end-to-end transport protocols,
3
Established state, 103
exceptions
handshake timeouts, 102
multiple sockets with same
address, 108
security, 91
thread errors, 68
explicit-length fields, 43
factories, 68-71, 75, 89-90
factoring servers, 68-71
fields
defined, 37
explicit-length, 43
Y ileClientA pplet. java, 91
FileL ogger. java, 66-67
File Transfer Protocol (FTP), 6
flow control mechanism, TCP,
98
f lush( ) method, 22
Framer. java, 45-46
framing, 42-46
getByName() method, 9-12
getBytes() methods, 40
getData() method, 25, 33-34
getInetAddress() method, 19
getLocalHost() method, 9-12
getPort () method, 19
get Propert i es() method, 73
graceful close mechanism,
104-107
GZIPOutputStream, 43, 89, 90
Half closed state, 105
handshake messages
closing, 105-107
defined, 3
establishing connections,
100-104
hosts, 1
Hypertext Transfer Protocol
(HTTP)
closing connections, 85-86
purpose of, 2
images, multicasting, 82
information
definition of, 2
encoding of. See encoding of
information
InetAddress class, 9-12
I netA ddressE x ample. j ava, 9 - 1 1
i n p u t / o u t p u t (I/O)
buffering, 4 2
closing. See c l o s e ( ) m e t h o d
input. See input streams
nonblocking, 75-79
output. See output streams
shutdown methods, 86-89,
105-106
input streams
closing. See close() method
composing, 42
creating, 21-23
framing, 42-46
Java classes, table of, 43
shutdownInput (), 86-89
TCP implementation, 55-56
write/read relationship, 96
InputStream, 13-14, 19, 21-23,
42
integer types, 40-41
internationalization, Java
support for, 39
Internet addresses, 4, 9-12,
93-94
Internet Protocol (IP), 2-3
IP addresses, 9-12, 93-94
ISO Latin I, 40
I temQ uoteSinConst. java,
51
ItemQuoteDecoderSin. java,
53-54
ItemQuoteDecoder. java, 47
ItemQuoteDecoderText. java,
49-51
ItemQuoteEncoderBin. java,
51-53
TtemQuoteEncoder. java, 46
It emQ uot eE nc oderT ex t, java,
4 8 - 4 9
I temQ uote. j ava, 3 8
I temQ uoteT ex tConst. j ava, 4 8
iterative servers, 6 1
III Index 1 1 5
joinGroup() method, 81. 83
joining a group, 81-82
keepalive message behavior, 16
layers of TCP/IP, 2-3
leaveGroup() method, 83
length of datagrams, setting, 25
lengths of messages, 43
lingering, 17
little-endian byte order, 41, 44
local broadcast addresses, 79
local host IP addresses,
obtaining, 9-10
Logger. j ava, 65-66
logging, 64-67
loopback address, 4
memory limitations, deadlocks
from, 97-98
message boundari es
not preserved by TCP, 15
preserved by UDP, 23
messages
defined, 3 7
delimiters, 43-44, 47
encoding. See encoding of
information
framing, 42-43
multicast groups, 81-82
multicasting, 80-84
MulticastSoeket class, 80-84
multiplexing, demultiplexing
process, 107-109
multitasking, 61-75
factoring servers, 68-71,
74-75
nonblocking I/O, 75-79
pooled threads, 61, 71-75
server protocol, 63-67
thread-per-client, 67-68
threads. See threads
Nagle's algorithm, 17
names of Internet hosts, 4-5,
10-11
network byte order, 41
network layer, 3
network protocols. See
protocols; Transmission
Control Protocol (TCP);
User Datagram Protocol
(UDP)
networks, 1
nextToken() method, 44-46
nonblocking I/O, 75-79
numbers, transmitting, 40-42
options, socket, 84-85
out put streams
composing, 42
defined, 21-23
flushing, 94
framing, 42-46
Java classes, table of, 43
shutdown0utput (), 86-89
TCP implementation, 55-56
wri t e/ read relationship,
95-96
0utputStream, 13-14, 19, 21-23,
42
OutputStreamWriter, 40
packets
addresses, 3
defined, 2
message boundaries, 15, 23
Time To Live (TTL) values, 81,
83
parsing, 37, 43-45
peers, 5
PoolDispatcher. j ava, 7 1 - 7 3
port n u m b e r s
defined, 3 - 4
f inding b y client, 5 - 6
getPort () method, 19
multiple sockets with,
107-109
socket structures, 93-94
price quote information
example, 37-38
P r i n t W r i t e r , 1 O 0
properties, 73
ProtocolFactory. java, 69,
77-79
protocols
closing connections, 85-90
compression. See
compressi on protocol
defined, 2
factoring, 68-71, 74-75
HTTP, 2, 85-86
IP, 2-3
TCP. See Transmission
Control Protocol (TCP)
in TCP/IP suite, 2
timing out, 76-77
UDP. See User Datagram
Protocol (UDP)
queues, data, 94-99
read () met hod
blocking by, 75-76
correspondence with wri t e(),
96
data at server, 20
end-of-stream indication, 43
grouping data with TCP
socket, 96
maxi mum timeout, setting,
17
message boundaries, 15
performance vs. buffer size,
100
syntax, 22
Reader class delimiters, 43-44
recei ve() method, 24, 26,
29-34, 75-76
receiving data. See input st ream
RecvQ, 96-99, 105-106
RecvTCP. java, 56-57
RecvUDP. java, 58
RecvUDPMulticast. java, 82-83
reliable byte-stream channels, 3,
94-97, 100
Remote Method Invocation
(RMI), 91
ret ransmi ssi on of packets.
See reliable byt e-st ream
channels
routers, 1-2
run() method, 62-65
Runnable interface, 62-65, 69
security of applets, 91
send () met hod
buffer limits, 98
DatagramSocket class, 24, 26,
28, 31-34
sending data. See out put streams
SendQ, 96-99, 105-106
SendTCP. java, 55-56
SendUPD. j ava, 5 7
SendUDPMulticast. j ava, 8 0 - 8 1
Serializable interface, 5 8 - 5 9
serialization capabilities, 58-59
servers
closing connections, 85-90
compression, 86-90
concurrent. See multitasking
defined, 5
factoring, 68-71, 74-75
handshake events, 102-104
iterative, 61
loggers, 64-67
port numbers, 5-6
TCP. See TCP servers; TCP
sockets
text-encoded messages,
receiving, 56-57
thread-pool, 71-75
UDP, 31-33. See also UDP
sockets
ServerSocket class
accept() method, 18-19,
75-76, 103-104, 109
I I 6 I n d e x []
ServerSocket class (continued)
constructing server with,
18-21
constructors, 20-21
demultiplexing, 107-109
est abl i shment of connections,
103
met hods, 21
purpose of, 12
setReceiveBufferSize() method,
100
setSendBufferSize() method,
100
setSoLinger() method, 106
setSoTimeout() method, 76-77
shutdownlnput () method, 86
shutdown0utput () method,
86-89, 105-106
signed integers, 41
Socket class, 12-18
accept () met hod creating,
18-19
accessors, 16-17
blocked I/O, 76
buffer size, met hods for
setting, 100
connection est abl i shment
events, 101-104
constructors, 15-16, 108
creating socket instances,
13-14, 18-19
demultiplexing, 107-109
get l net Address() method, 19
get Port () method, 19
implementation, underlying,
18
instantiation by accept () at
server, 18
met hods, 16
shut down met hods, 86-89
socket options, 84-85
sockets
addresses, 9-12
creating, 13-14, 18-19
defaults, 84-85
defined, 6
identification, 6
servers. See ServerSocket
class
UDP. See UDP sockets
st ream sockets, 6
st reams
composition, 42
decoding, 54
encoding. See encoding of
i nformat i on
end-of-stream indication, 43
input. See input streams
interface integer methods, 41
output. See out put streams
structures, socket
connection establishment
events affecting, 101-104
fields, multiplexing, 107-108
Half closed state, 105
Internet addresses of sockets,
93-94
ports of sockets, 93-94
protocol state information,
94
queues of data, 94
Socket instances, 93-94
wildcard values, 107-109
system properties, 73-74
TCP clients, 12-18
TCP connections
closing, 15, 85-90, 104-10 7
defined, 12
end-of-stream indication, 43
establishing, 12-13
TCPEchoClient. java, 13-15
TCP servers, 18-21
TCP sockets
buffering, 94-97
closing connections, 104-107
data structures, 94
i nput / out put streams, 21-23
reliable service requirements,
3, 94-97, 100
ServerSocket class, 20-21
socket class, 15-18
TCP clients, 12-18
TCP servers, 18-21
wri t e/ read relationship, 96
TCPEchoClient. java, 13-15
TCPEchoServer. java, 18-20
TCPEchoServerThread. java,
67-68
TfiPFileServer. java, 91
text data, 39-40, 47-51
t hread pools, 61, 71-75
ThreadExample. java, 62-63
ThreadMain. java, 74-75
thread-per-client, 61, 67-68
ThreadPerDispatcher. java, 70
threads, 61- 75
creating, 62, 68
deadlock, avoiding with, 99
exceptions, 68
nonblocking I/O, 75-79
resources consumed, 71
reusing. See thread pools
Runnable interface, 62-65, 69
server protocol, 63-67
suspending, 63
thread-per-client, 61, 67-68
time, maxi mum blocking,
76-79
watchdog, 78-79
T imeL imitE choProtocol, 77-78
T ime L imi tE cho Pro t oc o I F a c tory. java,
77-79
time, m a x i m u m blocking, 76-79
T i m e T o L ive ( T T L ) values, 8 i, 8 3
Time-Wait state, 105, 107
timing out of handshakes, 102
Transmission Control Protocol
(TCP), 2-3. See also TCP
sockets
t ransport layer, 3
two' s-complement
representation, 41
UDP clients, 26-31
UDP sockets, 23-35
creating, 28
DatagramPacket class, 2 4 - 2 6
e n c o d i n g i n f o r m a t i o n for,
57-58
getData() method, 25, 33-34
I/O with, 33-34
lost datagrams, 26
multicasting, 80-84
sending datagrams, 28-29
UDP clients, 26-31
UDP servers, 31-33
UDPE choClientT imeout. java,
2 7 - 2 9
UDPE choServer. j ava, 3 1 - 3 3
vs. T C P sockets, 2 3
UDPE choClientT imeout. java,
2 7 - 2 9
UDPEchoServer. j ava, 3 1 - 3 3
unicast, 7 9
U n i c o d e encodings, 39, 4 4 - 4 5
unsi gned integers, 41
User Datagram Protocol (UDP)
dat agram sockets, 6
functions of, 23
part of TCP/IP, 2
purpose of, 3
wildcard values, 107-109
wri t e() met hod
blocking by, 75-77, 98
buffer parameters, 20
correspondence with read (),
96
message boundaries, 15
performance vs. buffer size,
100
syntax, 22

Das könnte Ihnen auch gefallen