📄 tij0164.html
字号:
<font color="#0000ff">try</font> {
System.out.println(
"Connection accepted: "+ socket);
BufferedReader in =
<font color="#0000ff">new</font> BufferedReader(
<font color="#0000ff">new</font> InputStreamReader(
socket.getInputStream()));
<font color="#009900">// Output is automatically flushed</font>
<font color="#009900">// by PrintWriter:</font>
PrintWriter out =
<font color="#0000ff">new</font> PrintWriter(
<font color="#0000ff">new</font> BufferedWriter(
<font color="#0000ff">new</font> OutputStreamWriter(
socket.getOutputStream())),<font color="#0000ff">true</font>);
<font color="#0000ff">while</font> (<font color="#0000ff">true</font>) {
String str = in.readLine();
<font color="#0000ff">if</font> (str.equals("END")) <font color="#0000ff">break</font>;
System.out.println("Echoing: " + str);
out.println(str);
}
<font color="#009900">// Always close the two sockets...</font>
} <font color="#0000ff">finally</font> {
System.out.println("closing...");
socket.close();
}
} <font color="#0000ff">finally</font> {
s.close();
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
just needs a port number, not an IP address (since it’s running on
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>this</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
machine!). When you call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>accept( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>blocks</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
until some client tries to connect to it. That is, it’s there waiting for
a connection but other processes can run (see Chapter 14). When a connection is
made,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>accept( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
returns with a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object representing that connection.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
responsibility for cleaning up the sockets is crafted carefully here. If the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor fails, the program just quits (notice we must assume that the
constructor for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
doesn’t leave any open network sockets lying around if it fails). For
this case,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>throws</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>IOException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
so a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block is not necessary. If the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor is successful then all other method calls must be guarded in a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try-finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block to ensure that, no matter how the block is left, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is properly closed.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
same logic is used for the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
returned by
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>accept( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>accept( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
fails, then we must assume that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
doesn’t exist or hold any resources, so it doesn’t need to be
cleaned up. If it’s successful, however, the following statements must be
in a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try-finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block so that if they fail the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will still be cleaned up. Care is required here because sockets use important
non-memory resources, so you must be diligent in order to clean them up (since
there is no destructor in Java to do it for you).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Both
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
produced by
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>accept( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are printed to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>System.out</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This means that their
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods are automatically called. These produce:
</FONT><P></DIV>
<font color="#990000"><PRE>ServerSocket[addr=0.0.0.0,PORT=0,localport=8080]
Socket[addr=127.0.0.1,PORT=1077,localport=8080]</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Shortly,
you’ll see how these fit together with what the client is doing.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
next part of the program looks just like opening files for reading and writing
except that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>OutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are created from the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object. Both the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>OutputStream
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">objects
are converted to Java 1.1<A NAME="Index2639"></A>
<A NAME="Index2640"></A><A NAME="Index2641"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Reader
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
<A NAME="Index2642"></A><A NAME="Index2643"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Writer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects using the “converter” classes <A NAME="Index2644"></A><A NAME="Index2645"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStreamReader</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and <A NAME="Index2646"></A><A NAME="Index2647"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>OutputStreamWriter</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
respectively. You could also have used the Java 1.0<A NAME="Index2648"></A>
<A NAME="Index2649"></A><A NAME="Index2650"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and <A NAME="Index2651"></A><A NAME="Index2652"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>OutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
classes directly, but with output there’s a distinct advantage to using
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Writer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
approach. This appears with <A NAME="Index2653"></A><A NAME="Index2654"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>PrintWriter</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which has an overloaded constructor that takes a second argument, a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>boolean
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">flag
that indicates whether to automatically flush the output at the end of each
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>println( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(but
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>not
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>print( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
statement. Every time you write to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>out</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
its buffer must be flushed so the information goes out over the network.
Flushing is important for this particular example because the client and server
each wait for a line from the other party before proceeding. If flushing
doesn’t occur, the information will not be put onto the network until the
buffer is full, which causes lots of problems in this example.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
writing network programs you need to be careful about using automatic flushing.
Every time you flush the buffer a packet must be created and sent. In this
case, that’s exactly what we want, since if the packet containing the
line isn’t sent then the handshaking back and forth between server and
client will stop. Put another way, the end of a line is the end of a message.
But in many cases messages aren’t delimited by lines so it’s much
more efficient to not use auto flushing and instead let the built-in buffering
decide when to build and send a packet. This way, larger packets can be sent
and the process will be faster.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Note
that, like virtually all streams you open, these are buffered. There’s an
exercise at the end of the chapter to show you what happens if you don’t
buffer the streams (things get slow).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
infinite
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>while</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
loop reads lines from the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
BufferedReader in
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
writes information to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>System.out</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and to the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>PrintWriter</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>out</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -