?? ch9.htm
字號(hào):
ioe)<BR> {<BR> System.out.println("Errorin SimpleWebServer: " + ioe);<BR> }<BR> }<BR><BR> public static void ServiceClient(Socketclient)<BR> throws IOException<BR> {<BR> DataInputStreaminbound = null;<BR> DataOutputStreamoutbound = null;<BR> try<BR> {<BR> //Acquire the streams for IO<BR> inbound= new DataInputStream( client.getInputStream());<BR> outbound= new DataOutputStream( client.getOutputStream());<BR><BR> //Format the output (response header and tiny HTML document)<BR> StringBufferbuffer = PrepareOutput();<BR><BR> StringinputLine;<BR> while((inputLine = inbound.readLine()) != null)<BR> {<BR> //If end of HTTP request, send the response<BR> if( inputLine.equals("") )<BR> {<BR> outbound.writeBytes(buffer.toString());<BR> break;<BR> }<BR> }<BR> }<BR> finally<BR> {<BR> //Clean up<BR> System.out.println("Cleaningup connection: " + client);<BR> outbound.close();<BR> inbound.close();<BR> client.close();<BR> client.close();<BR> }<BR> }</TT></BLOCKQUOTE><HR><P>Servers do not actively create connections. Instead, they passivelylisten for a client connect request and then provide their services.Servers are created with a constructor from the ServerSocket class.The following line creates a server socket and binds it to port80:<BLOCKQUOTE><TT>ServerSocket serverSocket = new ServerSocket(80,5);</TT></BLOCKQUOTE><P>The first parameter is the port number on which the server shouldlisten. The second parameter is optional. The API documentationindicates that this parameter is a listen time, but in traditionalsockets programming the listen function's second parameter isthe listen stack depth. As it turns out, this is also true forthe second constructor parameter. A server can receive connectrequests from many clients at the same time, but each call mustbe processed one at a time. The <I>listen stack</I> is a queueof unanswered connect requests. The above code instructs the socketdriver to maintain the last five connect requests. If the constructoromits the listen stack depth, a default value of <TT>50</TT>is used.<P>Once the socket is created and listening for connections, incomingconnections are created and placed on the listen stack. The <TT>accept()</TT>method is called to lift individual connections off the stack:<BLOCKQUOTE><TT>Socket clientSocket = serverSocket.accept();</TT></BLOCKQUOTE><P>This method returns a connected client socket used to conversewith the caller. No conversations are ever conducted over theserver socket itself. Instead, the server socket will spawn anew socket in the <TT>accept()</TT>method. The server socket is still open and queuing new connectionrequests.<P>Like the client socket, the next step is to create an input andoutput stream:<BLOCKQUOTE><TT>DataInputStream inbound = new DataInputStream(clientSocket.getInputStream() );<BR>DataOutputStream outbound = new DataOutputStream( clientSocket.getOutputStream());</TT></BLOCKQUOTE><P>Normal I/O operations can now be performed by using the newlycreated streams. This server waits for the client to send a blankline before sending its response. When the conversation is finished,the server closes the streams and the client socket. At this point,the server tries to accept more calls. What happens when thereare no calls waiting in the queue? The method will wait for oneto arrive. This behavior is known as <I>blocking</I>. The <TT>accept()</TT>method will block the server thread from performing any othertasks until a new call arrives. When five connects have been serviced,will be canceled.<P>All servers follow the same basic script:<OL><LI>Create the server socket and begin listening.<LI>Call the <TT>accept()</TT> methodto get new connections.<LI>Create input and output streams for the returned socket.<LI>Conduct the conversation based on the agreed protocol.<LI>Close the client streams and socket.<LI>Go back to step 2, or continue to step 7.<LI>Close the server socket.</OL><P>Figure 9.1<B> </B>summarizes the steps needed for client/serverconnection-oriented applications.<P><A HREF="f9-1.gif" ><B>Figure 9.1:</B> <I>Client and server connection-oriented applications.</I></A><H3><A NAME="IterativeandConcurrentServers">Iterative and ConcurrentServers</A></H3><P>The application just presented is known as an <I>iterative server</I>because the code accepts a client connection and completely processesit before it will accept another connection. More complex serversare concurrent. Instead of accepting connections and immediatelyprocessing them, a <I>concurrent server</I> spawns a new threadto process each new request, so it seems as though the serveris processing many requests simultaneously. All commercial Webservers are concurrent servers.<H3><A NAME="JavaDatagramClasses">Java Datagram Classes</A></H3><P>Unlike connection-oriented classes, the datagram versions of theclient and server behave in nearly identical manners-the onlydifference occurs in implementation. The same class is used forboth client and server halves. The following lines create clientand server datagram sockets:<BLOCKQUOTE><TT>DatagramSocket serverSocket = new DatagramSocket(4545 );<BR>DatagramSocket clientSocket = new DatagramSocket();</TT></BLOCKQUOTE><P>The server specifies its port using the lone constructor parameter<TT>4545</TT>. Since the client willcall the server, the client can use any available port. The omittedconstructor parameter in the second call instructs the operatingsystem to assign the next available port number. The client couldhave requested a specific port, but the call would fail if someother socket had already bound itself to that port. It's betternot to specify a port unless the intent is to be a server.<P>Since streams can't be acquired for communication, how do youtalk to a DatagramSocket? The answer lies in the DatagramPacketclass.<H4>Receiving Datagrams</H4><P>The DatagramPacket class is used to receive and send data overDatagramSocket classes. The packet class contains connection informationas well as the data. As was explained earlier, datagrams are self-containedtransmission units. The DatagramPacket class encapsulates theseunits. The following lines receive data from a datagram socket:<BLOCKQUOTE><TT>DatagramPacket packet = new DatagramPacket(newbyte[512], 512);<BR>clientSocket.receive(packet);</TT></BLOCKQUOTE><P>The constructor for the packet needs to know where to place thereceived data. A 512-byte buffer was created and passed to theconstructor as the first parameter. The second constructor parameterwas the size of the buffer. Like the <TT>accept()</TT>method in the ServerSocket class, the <TT>receive()</TT>method will block until data is available.<H4>Sending Datagrams</H4><P>Sending datagrams is really very simple; all that's needed isa complete address. Addresses are created and tracked by usingthe InetAddress class. This class has no public constructors,but it does contain several static methods that can be used tocreate an instance of the class. The following list shows thepublic methods that create InetAddress class instances:<BR><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD WIDTH=541><I>Public InetAddress Creation Methods</I></TD></TR><TR VALIGN=TOP><TD WIDTH=541><BLOCKQUOTE><TT>InetAddress getByName(String host);<BR>InetAddress[] getAllByName(String host);<BR>InetAddress getLocalHost();</TT></BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>Getting the local host is useful for informational purposes, butonly the first two methods are actually used for sending packets.Both <TT>getByName()</TT> and <TT>getAllByName()</TT>require the name of the destination host. The first method merelyreturns the first match it finds. The second method is neededbecause a computer can have more than one address. When this occurs,the computer is said to be <I>multi-homed</I>. The computer hasone name, but multiple ways to reach it.<P>All the creation methods are marked as static. They must be calledas follows:<BLOCKQUOTE><TT>InetAddress addr1 = InetAddress.getByName("merlin");<BR>InetAddress addr2[] = InetAddress.getAllByName("merlin");<BR>InetAddress addr3 = InetAddress.getLocalHost();</TT></BLOCKQUOTE><P>Any of these calls can throw an UnknownHostException. If a computeris not connected to a Domain Name Server (DNS) or if the hostis really not found, an exception will be thrown. If a computerdoes not have an active TCP/IP configuration, then <TT>getLocalHost()</TT>is likely to fail with this exception as well.<P>Once an address is determined, datagrams can be sent. The followinglines transmit a String to a destination socket:<BLOCKQUOTE><TT>String toSend = "This is the datato send!");<BR>byte[] sendbuf = new byte[ toSend.length() ];<BR>toSend.getBytes( 0, toSend.length(), sendbuf, 0 );<BR>DatagramPacket sendPacket = new DatagramPacket( sendbuf, sendbuf.length,addr, port);<BR>clientSocket.send( sendPacket );</TT></BLOCKQUOTE><P>First, the string must be converted to a byte array. The <TT>getBytes()</TT>method takes care of the conversion. Next, a new DatagramPacketinstance must be created. Notice the two extra parameters at theend of the constructor. Since this will be a send packet, theaddress and port of the destination must also be placed into thepacket. An applet may know the address of its server, but howdoes a server know the address of its client? Remember that adatagram is like an envelope-it has a return address. When anypacket is received, the return address can be extracted from thepacket by using <TT>getAddress()</TT>and <TT>getPort()</TT>. This is howa server would respond to a client packet:<BLOCKQUOTE><TT>DatagramPacket sendPacket = new DatagramPacket(sendbuf, sendbuf.length,<BR> recvPacket.getAddress(), recvPacket.getPort());<BR>serverSocket.send( sendPacket );</TT></BLOCKQUOTE><P>Unlike connection-oriented operation, datagram servers are actuallyless complicated than the datagram client.<H4>Datagram Servers</H4><P>The basic script for datagram servers is as follows:<OL><LI>Call receive to wait for incoming packets.<LI>Respond to received packets according to the agreed protocol.<LI>Go back to step 2, or continue to step 5.<LI>Close the datagram socket.</OL><P>Listing 9.3 shows a simple datagram echo server. It will echoback any packets it receives.<HR><BLOCKQUOTE><B>Listing 9.3. A simple datagram echo server.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>import java.io.*;<BR>import java.net.*;<BR>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -