📄 tij0165.html
字号:
the creation of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServerSocket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
fails, the exception is again thrown through
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
But if it succeeds, the outer
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try-finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
guarantees its cleanup. The inner
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try-catch</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
guards only against the failure of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServeOneJabber</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor; if the constructor succeeds, then the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ServeOneJabber</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
thread will close the associated socket.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final
int maxthreads
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
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><P></DIV>
<font color="#990000"><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("Making client " + 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("Client " + id + ": " + i);
String str = in.readLine();
System.out.println(str);
}
out.println("END");
} <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">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>JabberClientThread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor takes an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InetAddress</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and uses it to open a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
You’re probably starting to see the pattern: the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Socket</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is always used to create some kind of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Reader
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and/or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Writer
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and/or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>OutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
object, which is the only way 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">
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,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>start( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
performs thread initialization and calls
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>close( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for the socket is relegated to the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>threadcount</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keeps track of how many
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>JabberClientThread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects currently exist. It is incremented as part of the constructor and
decremented as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
exits (which means the thread is terminating). In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MultiJabberClient.main( ),</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MAX_THREADS</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to see where your particular system begins to have trouble with too many
connections.
</FONT><a name="_Toc408018771"></a><a name="_Toc375545498"></a><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0164.html">Prev</a> | <a href="tij0166.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -