📄 chapter15.html
字号:
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=#009900>// If any of the above calls throw an </font>
<font color=#009900>// exception, the caller is responsible for</font>
<font color=#009900>// closing the socket. Otherwise the thread</font>
<font color=#009900>// will close it.</font>
start(); <font color=#009900>// Calls run()</font>
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> run() {
<font color=#0000ff>try</font> {
<font color=#0000ff>while</font> (<font color=#0000ff>true</font>) {
String str = in.readLine();
<font color=#0000ff>if</font> (str.equals(<font color=#004488>"END"</font>)) <font color=#0000ff>break</font>;
System.out.println(<font color=#004488>"Echoing: "</font> + str);
out.println(str);
}
System.out.println(<font color=#004488>"closing..."</font>);
} <font color=#0000ff>catch</font> (IOException e) {
} <font color=#0000ff>finally</font> {
<font color=#0000ff>try</font> {
socket.close();
} <font color=#0000ff>catch</font>(IOException e) {}
}
}
}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> MultiJabberServer {
<font color=#0000ff>static</font> <font color=#0000ff>final</font> <font color=#0000ff>int</font> PORT = 8080;
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args)
<font color=#0000ff>throws</font> IOException {
ServerSocket s = <font color=#0000ff>new</font> ServerSocket(PORT);
System.out.println(<font color=#004488>"Server Started"</font>);
<font color=#0000ff>try</font> {
<font color=#0000ff>while</font>(<font color=#0000ff>true</font>) {
<font color=#009900>// Blocks until a connection occurs:</font>
Socket socket = s.accept();
<font color=#0000ff>try</font> {
<font color=#0000ff>new</font> ServeOneJabber(socket);
} <font color=#0000ff>catch</font>(IOException e) {
<font color=#009900>// If it fails, close the socket,</font>
<font color=#009900>// otherwise the thread will close it:</font>
socket.close();
}
}
} <font color=#0000ff>finally</font> {
s.close();
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>ServeOneJabber </B>thread
takes the <B>Socket</B> object that’s produced by <B>accept( )</B> in
<B>main( )</B> every time a new client makes a connection. Then, as before,
it creates a <B>BufferedReader</B> and auto-flushed <B>PrintWriter</B> object
using the <B>Socket</B>. Finally, it calls the special <B>Thread</B> method
<B>start( )</B>, which performs thread initialization and then calls
<B>run( )</B>. This performs the same kind of action as in the previous
example: reading something from the socket and then echoing it back until it
reads the special “END” signal.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The responsibility for cleaning up
the socket must again be carefully designed. In this case, the socket is created
outside of the <B>ServeOneJabber</B> so the responsibility can be shared. If the
<B>ServeOneJabber</B> constructor fails, it will just throw the exception to the
caller, who will then clean up the thread. But if the constructor succeeds, then
the <B>ServeOneJabber</B> object takes over responsibility for cleaning up the
thread, in its <B>run( )</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Notice the simplicity of the
<B>MultiJabberServer</B>. As before, a <B>ServerSocket</B> is created and
<B>accept( )</B> is called to allow a new connection. But this time, the
return value of <B>accept( )</B> (a <B>Socket</B>) is passed to the
constructor for <B>ServeOneJabber,</B> which creates a new thread to handle that
connection. When the connection is terminated, the thread simply goes
away.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If the creation of the
<B>ServerSocket</B> fails, the exception is again thrown through
<B>main( )</B>. But if it succeeds, the outer <B>try-finally</B> guarantees
its cleanup. The inner <B>try-catch</B> guards only against the failure of the
<B>ServeOneJabber</B> constructor; if the constructor succeeds, then the
<B>ServeOneJabber</B> thread will close the associated socket.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To test that the server really does
handle multiple clients, the following program creates many clients (using
threads) that connect to the same server. Each thread has a limited lifetime,
and when it goes away, that leaves space for the creation of a new thread. The
maximum number of threads allowed is determined by the <B>final int
maxthreads</B>. You’ll notice that this value is rather critical, since if
you make it too high the threads seem to run out of resources and the program
mysteriously fails.</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: MultiJabberClient.java</font>
<font color=#009900>// Client that tests the MultiJabberServer</font>
<font color=#009900>// by starting up multiple clients.</font>
<font color=#0000ff>import</font> java.net.*;
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>class</font> JabberClientThread <font color=#0000ff>extends</font> Thread {
<font color=#0000ff>private</font> Socket socket;
<font color=#0000ff>private</font> BufferedReader in;
<font color=#0000ff>private</font> PrintWriter out;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>int</font> counter = 0;
<font color=#0000ff>private</font> <font color=#0000ff>int</font> id = counter++;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>int</font> threadcount = 0;
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>int</font> threadCount() {
<font color=#0000ff>return</font> threadcount;
}
<font color=#0000ff>public</font> JabberClientThread(InetAddress addr) {
System.out.println(<font color=#004488>"Making client "</font> + id);
threadcount++;
<font color=#0000ff>try</font> {
socket =
<font color=#0000ff>new</font> Socket(addr, MultiJabberServer.PORT);
} <font color=#0000ff>catch</font>(IOException e) {
<font color=#009900>// If the creation of the socket fails, </font>
<font color=#009900>// nothing needs to be cleaned up.</font>
}
<font color=#0000ff>try</font> {
in =
<font color=#0000ff>new</font> BufferedReader(
<font color=#0000ff>new</font> InputStreamReader(
socket.getInputStream()));
<font color=#009900>// Enable auto-flush:</font>
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>);
start();
} <font color=#0000ff>catch</font>(IOException e) {
<font color=#009900>// The socket should be closed on any </font>
<font color=#009900>// failures other than the socket </font>
<font color=#009900>// constructor:</font>
<font color=#0000ff>try</font> {
socket.close();
} <font color=#0000ff>catch</font>(IOException e2) {}
}
<font color=#009900>// Otherwise the socket will be closed by</font>
<font color=#009900>// the run() method of the thread.</font>
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> run() {
<font color=#0000ff>try</font> {
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 25; i++) {
out.println(<font color=#004488>"Client "</font> + id + <font color=#004488>": "</font> + i);
String str = in.readLine();
System.out.println(str);
}
out.println(<font color=#004488>"END"</font>);
} <font color=#0000ff>catch</font>(IOException e) {
} <font color=#0000ff>finally</font> {
<font color=#009900>// Always close it:</font>
<font color=#0000ff>try</font> {
socket.close();
} <font color=#0000ff>catch</font>(IOException e) {}
threadcount--; <font color=#009900>// Ending this thread</font>
}
}
}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> MultiJabberClient {
<font color=#0000ff>static</font> <font color=#0000ff>final</font> <font color=#0000ff>int</font> MAX_THREADS = 40;
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args)
<font color=#0000ff>throws</font> IOException, InterruptedException {
InetAddress addr =
InetAddress.getByName(<font color=#0000ff>null</font>);
<font color=#0000ff>while</font>(<font color=#0000ff>true</font>) {
<font color=#0000ff>if</font>(JabberClientThread.threadCount()
< MAX_THREADS)
<font color=#0000ff>new</font> JabberClientThread(addr);
Thread.currentThread().sleep(100);
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>JabberClientThread</B>
constructor takes an <B>InetAddress</B> and uses it to open a <B>Socket</B>.
You’re probably starting to see the pattern: the <B>Socket</B> is always
used to create some kind of <B>Reader </B>and/or <B>Writer </B>(or
<B>InputStream</B> and/or <B>OutputStream</B>) object, which is the only way
that the <B>Socket</B> can be used. (You can, of course, write a class or two to
automate this process instead of doing all the typing if it becomes painful.)
Again, <B>start( )</B> performs thread initialization and calls
<B>run( )</B>. Here, messages are sent to the server and information from
the server is echoed to the screen. However, the thread has a limited lifetime
and eventually completes. Note that the socket is cleaned up if the constructor
fails after the socket is created but before the constructor completes.
Otherwise the responsibility for calling <B>close( )</B> for the socket is
relegated to the <B>run( )</B> method.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>threadcount</B> keeps track
of how many <B>JabberClientThread</B> objects currently exist. It is incremented
as part of the constructor and decremented as <B>run( )</B> exits (which
means the thread is terminating). In <B>MultiJabberClient.main( ),</B> you
can see that the number of threads is tested, and if there are too many, no more
are created. Then the method sleeps. This way, some threads will eventually
terminate and more can be created. You can experiment with <B>MAX_THREADS</B> to
see where your particular system begins to have trouble with too many
connections.</FONT><A NAME="_Toc375545498"></A><A NAME="_Toc408018771"></A><BR></P></DIV>
<A NAME="Heading518"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Datagrams<BR><A NAME="Index2649"></A><A NAME="Index2650"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The examples you’ve seen so
far use the
<A NAME="Index2651"></A><A NAME="Index2652"></A><A NAME="Index2653"></A><I>Transmission
Control Protocol</I> (TCP, also known as
<A NAME="Index2654"></A><A NAME="Index2655"></A><A NAME="Index2656"></A><I>stream-based
sockets</I>), which is designed for ultimate reliability and guarantees that the
data will get there. It allows retransmission of lost data, it provides multiple
paths through different routers in case one goes down, and bytes are delivered
in the order they are sent. All this control and reliability comes at a cost:
TCP has a high overhead.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There’s a second protocol,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -