Recipe 17.2 Returning a Response (String or Binary)


Problem

You need to write a string or binary data to the client.

Solution

The socket gives you an InputStream and an OutputStream. Use them.

Discussion

The client socket examples in the previous chapter called the getInputStream( ) and getOutputStream( ) methods. These examples do the same. The main difference is that these ones get the socket from a ServerSocket's accept( ) method. Another distinction is, by definition, that normally the server creates or modifies the data and sends it to the client. Example 17-3 is a simple Echo server, which the Echo client of Recipe 16.4 can connect to. This server handles one complete connection with a client, then goes back and does the accept( ) to wait for the next client.

Example 17-3. EchoServer.java
/**  * EchoServer - create server socket, do I-O on it.  */ public class EchoServer {     /** Our server-side rendezvous socket */     protected ServerSocket sock;     /** The port number to use by default */     public final static int ECHOPORT = 7;     /** Flag to control debugging */     protected boolean debug = true;     /** main: construct and run */     public static void main(String[] argv) {         new EchoServer(ECHOPORT).handle(  );     }     /** Construct an EchoServer on the given port number */     public EchoServer(int port) {         try {             sock = new ServerSocket(port);         } catch (IOException e) {             System.err.println("I/O error in setup");             System.err.println(e);             System.exit(1);         }     }     /** This handles the connections */     protected void handle(  ) {         Socket ios = null;         BufferedReader is = null;         PrintWriter os = null;         while (true) {             try {                 ios = sock.accept(  );                 System.err.println("Accepted from " +                     ios.getInetAddress(  ).getHostName(  ));                 is = new BufferedReader(                     new InputStreamReader(ios.getInputStream(  ), "8859_1"));                 os = new PrintWriter(                         new OutputStreamWriter(                             ios.getOutputStream(  ), "8859_1"), true);                 String echoLine;                 while ((echoLine = is.readLine(  )) != null) {                     System.err.println("Read " + echoLine);                     os.print(echoLine + "\r\n"); os.flush(  );                     System.err.println("Wrote " + echoLine);                 }                 System.err.println("All done!");             } catch (IOException e) {                 System.err.println(e);             } finally {                 try {                     if (is != null)                         is.close(  );                     if (os != null)                         os.close(  );                     if (ios != null)                         ios.close(  );                 } catch (IOException e) {                     // These are unlikely, but might indicate that                     // the other end shut down early, a disk filled up                     // but wasn't detected until close, etc.                     System.err.println("IO Error in close");                 }             }         }         /*NOTREACHED*/     } }

To send a string across an arbitrary network connection, some authorities recommend sending both the carriage return and the newline character. This explains the \r\n in the code. If the other end is a DOS program or a Telnet-like program, it may be expecting both characters. On the other hand, if you are writing both ends, you can simply use println( ) followed always by an explicit flush( ) before you read to prevent the deadlock of having both ends trying to read with one end's data still in the PrintWriter's buffer!

If you need to process binary data, use the data streams from java.io instead of the readers/writers. I need a server for the DaytimeBinary program of Recipe Recipe 16.5. In operation, it should look like the following.

C:\javasrc\network>java DaytimeBinary Remote time is 3161316799 BASE_DIFF is 2208988800 Time diff == 952284799 Time on localhost is Sun Mar 05 19:33:19 GMT 2000 C:\javasrc\network>time/t Current time is  7:33:23.84p C:\javasrc\network>date/t Current date is Sun 03-05-2000 C:\javasrc\network>

Well, it happens that I have such a program in my arsenal, so I present it in Example 17-4. Note that it directly uses certain public constants defined in the client class. Normally these are defined in the server class and used by the client, but I wanted to present the client code first.

Example 17-4. DaytimeServer.java
/**  * DaytimeServer - send the binary time.  */ public class DaytimeServer {     /** Our server-side rendezvous socket */     ServerSocket sock;     /** The port number to use by default */     public final static int PORT = 37;     /** main: construct and run */     public static void main(String[] argv) {         new DaytimeServer(PORT).runService(  );     }     /** Construct a DaytimeServer on the given port number */     public DaytimeServer(int port) {         try {             sock = new ServerSocket(port);         } catch (IOException e) {             System.err.println("I/O error in setup\n" + e);             System.exit(1);         }     }     /** This handles the connections */     protected void runService(  ) {         Socket ios = null;         DataOutputStream os = null;         while (true) {             try {                 System.out.println("Waiting for connection on port " + PORT);                 ios = sock.accept(  );                 System.err.println("Accepted from " +                     ios.getInetAddress(  ).getHostName(  ));                 os = new DataOutputStream(ios.getOutputStream(  ));                 long time = System.currentTimeMillis(  );                 time /= DaytimeBinary.MSEC;    // Daytime Protocol is in seconds                 // Convert to Java time base.                 time += DaytimeBinary.BASE_DIFF;                 // Write it, truncating cast to int since it is using                 // the Internet Daytime protocol which uses 4 bytes.                 // This will fail in the year 2038, along with all                 // 32-bit timekeeping systems based from 1970.                 // Remember, you read about the Y2038 crisis here first!                 os.writeInt((int)time);                 os.close(  );             } catch (IOException e) {                 System.err.println(e);             }         }     } }



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net