⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap15.htm

📁 Thinking in Java, 2nd edition
💻 HTM
📖 第 1 页 / 共 5 页
字号:
to be a socket but instead to make a <B>Socket</B> object when someone else
connects to it. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I25' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I26>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">However, the <B>ServerSocket</B> does
create a physical &#8220;server&#8221; or listening socket on the host machine.
This socket listens for incoming connections and then returns an
&#8220;established&#8221; socket (with the local and remote endpoints defined)
via the <B>accept(&#160;)</B> method. The confusing part is that both of these
sockets (listening and established) are associated with the same server socket.
The listening socket can accept only new connection requests and not data
packets. So while <B>ServerSocket</B> doesn&#8217;t make much sense
programmatically, it does &#8220;physically.&#8221;

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I26' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I27>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When you create a <B>ServerSocket</B>,
you give it only a port number. You don&#8217;t have to give it an IP address
because it&#8217;s already on the machine it represents. When you create a
<B>Socket</B>, however, you must give both the IP address and the port number
where you&#8217;re trying to connect. (However, the <B>Socket</B> that comes
back from <B>ServerSocket.accept(&#160;)</B> already contains all this
information.)

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I27' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I28>
</FONT><A NAME="_Toc375545496"></A><BR></P></DIV>
<A NAME="Heading517"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
A simple server and client</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This example makes the simplest use of
servers and clients using sockets. All the server does is wait for a connection,
then uses the <B>Socket</B> produced by that connection to create an
<B>InputStream</B> and <B>OutputStream</B>. These are converted to a
<B>Reader</B> and a <B>Writer</B>, then wrapped in a <B>BufferedReader</B> and a
<B>PrintWriter</B>.<B> </B>After that, everything it reads from the
<B>BufferedReader</B> it echoes to the <B>PrintWriter</B> until it receives the
line &#8220;END,&#8221; at which time it closes the connection.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I28' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I29>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The client makes the connection to the
server, then creates an <B>OutputStream </B>and performs the same wrapping as in
the server. Lines of text are sent through the resulting <B>PrintWriter</B>. The
client also creates an <B>InputStream</B> (again, with appropriate conversions
and wrapping) to hear what the server is saying (which, in this case, is just
the words echoed back). 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I29' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I30>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Both the server and client use the same
port number and the client uses the local loopback address to connect to the
server on the same machine so you don&#8217;t have to test it over a network.
(For some configurations, you might need to be <I>connected</I> to a network for
the programs to work, even if you aren&#8217;t <I>communicating</I> over that
network.) 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I30' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I31>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here is the server:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c15:JabberServer.java</font>
<font color=#009900>// Very simple server that just</font>
<font color=#009900>// echoes whatever the client sends.</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>import</font> java.net.*;

<font color=#0000ff>public</font> <font color=#0000ff>class</font> JabberServer {  
  <font color=#009900>// Choose a port outside of the range 1-1024:</font>
  <font color=#0000ff>public</font> <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>"Started: "</font> + s);
    <font color=#0000ff>try</font> {
      <font color=#009900>// Blocks until a connection occurs:</font>
      Socket socket = s.accept();
      <font color=#0000ff>try</font> {
        System.out.println(
          <font color=#004488>"Connection accepted: "</font>+ 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(<font color=#004488>"END"</font>)) <font color=#0000ff>break</font>;
          System.out.println(<font color=#004488>"Echoing: "</font> + str);
          out.println(str);
        }
      <font color=#009900>// Always close the two sockets...</font>
      } <font color=#0000ff>finally</font> {
        System.out.println(<font color=#004488>"closing..."</font>);
        socket.close();
      }
    } <font color=#0000ff>finally</font> {
      s.close();
    }
  } 
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that the <B>ServerSocket</B>
just needs a port number, not an IP address (since it&#8217;s running on
<I>this</I> machine!). When you call <B>accept(&#160;)</B>, the method
<I>blocks</I> until some client tries to connect to it. That is, it&#8217;s
there waiting for a connection, but other processes can run (see Chapter 14).
When a connection is made, <B>accept(&#160;)</B> returns with a <B>Socket</B>
object representing that connection. 

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I31' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I32>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The responsibility for cleaning up the
sockets is crafted carefully here. If the <B>ServerSocket</B> constructor fails,
the program just quits (notice we must assume that the constructor for
<B>ServerSocket</B> doesn&#8217;t leave any open network sockets lying around if
it fails). For this case, <B>main(&#160;)</B> <B>throws</B> <B>IOException</B>
so a <B>try</B> block is not necessary. If the <B>ServerSocket</B> constructor
is successful then all other method calls must be guarded in a
<B>try-finally</B> block to ensure that, no matter how the block is left, the
<B>ServerSocket</B> is properly closed.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I32' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I33>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The same logic is used for the
<B>Socket</B> returned by <B>accept(&#160;)</B>. If <B>accept(&#160;)</B> fails,
then we must assume that the <B>Socket</B> doesn&#8217;t exist or hold any
resources, so it doesn&#8217;t need to be cleaned up. If it&#8217;s successful,
however, the following statements must be in a <B>try-finally</B> block so that
if they fail the <B>Socket</B> will still be cleaned up. Care is required here
because sockets use important nonmemory resources, so you must be diligent in
order to clean them up (since there is no destructor in Java to do it for you).

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I33' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I34>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Both the <B>ServerSocket</B> and the
<B>Socket</B> produced by <B>accept(&#160;)</B> are printed to
<B>System.out</B>. This means that their <B>toString(&#160;)</B> methods are
automatically called. These produce:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>ServerSocket[addr=0.0.0.0,PORT=0,localport=8080]
Socket[addr=127.0.0.1,PORT=1077,localport=8080]</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Shortly, you&#8217;ll see how these fit
together with what the client is doing.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I34' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I35>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The next part of the program looks just
like opening files for reading and writing except that the <B>InputStream</B>
and <B>OutputStream</B> are created from the <B>Socket</B> object. Both the
<B>InputStream</B> and <B>OutputStream </B>objects are converted to
<A NAME="Index2070"></A><A NAME="Index2071"></A><B>Reader </B>and
<A NAME="Index2072"></A><A NAME="Index2073"></A><B>Writer</B> objects using the
&#8220;converter&#8221; classes
<A NAME="Index2074"></A><A NAME="Index2075"></A><B>InputStreamReader</B> and
<A NAME="Index2076"></A><A NAME="Index2077"></A><B>OutputStreamWriter</B>,
respectively. You could also have used the Java 1.0
<A NAME="Index2078"></A><A NAME="Index2079"></A><B>InputStream</B> and
<A NAME="Index2080"></A><A NAME="Index2081"></A><B>OutputStream</B> classes
directly, but with output there&#8217;s a distinct advantage to using the
<B>Writer</B> approach. This appears with
<A NAME="Index2082"></A><A NAME="Index2083"></A><B>PrintWriter</B>, which has an
overloaded constructor that takes a second argument, a <B>boolean </B>flag that
indicates whether to automatically flush the output at the end of each
<B>println(&#160;)</B> (but <I>not </I><B>print(&#160;)</B>) statement. Every
time you write to <B>out</B>, 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&#8217;t occur, the information will not be put
onto the network until the buffer is full, which causes lots of problems in this
example. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I35' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I36>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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&#8217;s exactly what we
want, since if the packet containing the line isn&#8217;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&#8217;t delimited by lines so it&#8217;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. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I36' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I37>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that, like virtually all streams you
open, these are buffered. There&#8217;s an exercise at the end of this chapter
to show you what happens if you don&#8217;t buffer the streams (things get
slow). 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER15_I37' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER15_I38>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The infinite <B>while</B> loop reads

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -