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

📄 chapter15.html

📁 java 是一个很好的网络开发环境。由于它是通过解释的方法
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>InetAddress addr = InetAddress.getByName(<font color=#0000ff>null</font>);</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you hand
<B>getByName(&#160;)</B> a <B>null</B>, it defaults to using the
<B>localhost</B>. The <B>InetAddress</B> is what you use to refer to the
particular machine, and you must produce this before you can go any further. You
can&#8217;t manipulate the contents of an <B>InetAddress </B>(but you can print
them out, as you&#8217;ll see in the next example). The only way you can create
an <B>InetAddress</B> is through one of that class&#8217;s <B>static</B> member
methods <B>getByName(&#160;)</B> (which is what you&#8217;ll usually use),
<B>getAllByName(&#160;)</B>, or <B>getLocalHost(&#160;)</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can also produce the local
loopback address by handing it the string <B>localhost</B>:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>InetAddress.getByName(<font color=#004488>"localhost"</font>);</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">or by using its dotted quad form to
name the reserved IP number for the loopback:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>InetAddress.getByName(<font color=#004488>"127.0.0.1"</font>);</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">All three forms produce the same
result.</FONT><A NAME="_Toc375545494"></A><A NAME="_Toc408018767"></A><BR></P></DIV>
<A NAME="Heading514"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Port: a unique place <BR>within the machine</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">An IP address isn&#8217;t enough to
identify a unique server, since many servers can exist on one machine. Each IP
machine also contains <I>ports</I>, and when you&#8217;re setting up a client or
a server you must choose a <A NAME="Index2619"></A><A NAME="Index2620"></A>port
where both client and server agree to connect; if you&#8217;re meeting someone,
the IP address is the neighborhood and the port is the bar.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The port is not a physical location
in a machine, but a software abstraction (mainly for bookkeeping purposes). The
client program knows how to connect to the machine via its IP address, but how
does it connect to a desired service (potentially one of many on that machine)?
That&#8217;s where the port numbers come in as second level of addressing. The
idea is that if you ask for a particular port, you&#8217;re requesting the
service that&#8217;s associated with the port number. The time of day is a
simple example of a service. Typically, each service is associated with a unique
port number on a given server machine. It&#8217;s up to the client to know ahead
of time which port number the desired service is running on. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The system services reserve the use
of ports 1 through 1024, so you shouldn&#8217;t use those or any other port that
you know to be in use. The first choice for examples in this book will be port
8080 (in memory of the venerable old 8-bit Intel 8080 chip in my first computer,
a CP/M
machine).</FONT><A NAME="_Toc375545495"></A><A NAME="_Toc408018768"></A><BR></P></DIV>
<A NAME="Heading515"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Sockets</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <I>socket</I> is the software
abstraction used to represent the &#8220;terminals&#8221; of a connection
between two machines. For a given connection, there&#8217;s a socket on each
machine, and you can imagine a hypothetical &#8220;cable&#8221; running between
the two machines with each end of the &#8220;cable&#8221; plugged into a socket.
Of course, the physical hardware and cabling between machines is completely
unknown. The whole point of the abstraction is that we don&#8217;t have to know
more than is necessary.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In Java, you create a socket to
make the connection to the other machine, then you get an <B>InputStream</B> and
<B>OutputStream</B> (or, with the appropriate converters, <B>Reader</B> and
<B>Writer</B>)<B> </B>from the socket in order to be able to treat the
connection as an IO stream object. There are two stream-based socket classes: a
<B>ServerSocket</B> that a server uses to &#8220;listen&#8221; for incoming
connections and a <B>Socket</B> that a client uses in order to initiate a
connection. Once a client makes a socket connection, the <B>ServerSocket</B>
returns (via the <B>accept(&#160;)</B>
<A NAME="Index2621"></A><A NAME="Index2622"></A>method) a corresponding server
side <B>Socket</B> through which direct communications will take place. From
then on, you have a true <B>Socket</B> to <B>Socket</B> connection and you treat
both ends the same way because they <I>are</I> the same. At this point, you use
the methods
<A NAME="Index2623"></A><A NAME="Index2624"></A><B>getInputStream(&#160;)</B>
and
<A NAME="Index2625"></A><A NAME="Index2626"></A><B>getOutputStream(&#160;)</B>
to produce the corresponding <B>InputStream</B> and <B>OutputStream</B> objects
from each <B>Socket</B>. These must be wrapped inside buffers and formatting
classes just like any other stream object described in Chapter
10.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The use of the term
<B>ServerSocket</B> would seem to be another example of a confusing name scheme
in the Java libraries. You might think <B>ServerSocket</B> would be better named
&#8220;ServerConnector&#8221; or something without the word &#8220;Socket&#8221;
in it. You might also think that <B>ServerSocket</B> and <B>Socket</B> should
both be inherited from some common base class. Indeed, the two classes do have
several methods in common but not enough to give them a common base class.
Instead, <B>ServerSocket</B>&#8217;s job is to wait until some other machine
connects to it, then to return an actual <B>Socket</B>. This is why
<B>ServerSocket</B> seems to be a bit misnamed, since its job isn&#8217;t really
to be a socket but instead to make a <B>Socket</B> object when someone else
connects to it.</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;</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. (On the other hand, the
<B>Socket</B> that comes back from <B>ServerSocket.accept(&#160;)</B> already
contains all this
information.)</FONT><A NAME="_Toc375545496"></A><A NAME="_Toc408018769"></A><BR></P></DIV>
<A NAME="Heading516"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
A simple server and client</H3></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>. After that, everything it reads from
the <B>InputStream</B> it echoes to the <B>OutputStream</B> until it receives
the line END, at which time it closes the connection.</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>. Lines of text are sent through
the <B>OutputStream</B>. The client also creates an <B>InputStream</B> to hear
what the server is saying (which, in this case, is just the words echoed
back).</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 communicating over
that network.)</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>//: 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. </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.</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 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><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.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The next part of the program looks

⌨️ 快捷键说明

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