Java Reference
In-Depth Information
System
.
err
.
println
(
ex
.
getMessage
());
}
}
This is called an
iterative
server. There's one big loop, and in each pass through the loop
a single connection is completely processed. This works well for a very simple protocol
with very small requests and responses like daytime, though even with this simple a
protocol it's possible for one slow client to delay other faster clients. Upcoming examples
will address this with multiple threads or asynchronous I/O.
When exception handling is added, the code becomes somewhat more convoluted. It's
important to distinguish between exceptions that should probably shut down the server
and log an error message, and exceptions that should just close that active connection.
Exceptions within the scope of a particular connection should close that connection,
but not affect other connections or shut down the server. Exceptions outside the scope
of an individual request probably should shut down the server. To organize this, nest
the
try
blocks:
ServerSocket
server
=
null
;
try
{
server
=
new
ServerSocket
(
port
);
while
(
true
)
{
Socket
connection
=
null
;
try
{
connection
=
server
.
accept
();
Writer
out
=
new
OutputStreamWriter
(
connection
.
getOutputStream
());
Date
now
=
new
Date
();
out
.
write
(
now
.
toString
()
+
"\r\n"
);
out
.
flush
();
connection
.
close
();
}
catch
(
IOException
ex
)
{
// this request only; ignore
}
finally
{
try
{
if
(
connection
!=
null
)
connection
.
close
();
}
catch
(
IOException
ex
)
{}
}
}
}
catch
(
IOException
ex
)
{
ex
.
printStackTrace
();
}
finally
{
try
{
if
(
server
!=
null
)
server
.
close
();
}
catch
(
IOException
ex
)
{}
}
Always close a socket when you're finished with it. In
Chapter 8
, I said that a client
shouldn't rely on the other side of a connection to close the socket; that goes triple for
servers. Clients time out or crash; users cancel transactions; networks go down in high-
traffic periods; hackers launch denial-of-service attacks. For any of these or a hundred