Transferring Streams with Sockets

   

Java™ 2 Primer Plus
By Steven Haines, Steve Potts

Table of Contents
Chapter 20.  Network Programming


The preceding example showed how we can use the ObjectOutputStream and ObjectInputStream classes to send serializable objects via sockets. Another common need is to send streams via sockets. You can package streams as objects and send them using ObjectOutputStreams as demonstrated earlier in this chapter. This might not be the best-performing solution, however, especially when sending large quantities of streaming data.

A better choice in these cases is to use the PrintWriter and BufferedReader classes. Listing 20.10 shows a modified version of the LoopingSocketClient that uses these new I/O classes.

Listing 20.10 The BufferedSocketClient.java File
 /*   * BufferedSocketClient.java   *   * Created on October 2, 2002, 5:34 PM   */  package ch20;  import java.net.*;  import java.io.*;  /**   *   * @author  Stephen Potts   */  public class BufferedSocketClient  {      Socket socket1;      int portNumber = 1777;      String str = "";      /** Creates a new instance of BufferedSocketClient */      public BufferedSocketClient()      {          try          {              socket1 = new Socket(InetAddress.getLocalHost(),              portNumber);              BufferedReader br =  new BufferedReader(                        new InputStreamReader(socket1.getInputStream()));              PrintWriter pw =              new PrintWriter(socket1.getOutputStream(), true);              str = "initialize";              pw.println(str);              while ((str = br.readLine()) != null)              {                  System.out.println(str);                  pw.println("bye");                   if (str.equals("bye bye"))                      break;              }              br.close();              pw.close();              socket1.close();          } catch (Exception e)          {              System.out.println("Exception " + e);          }      }      public static void main(String args[])      {          BufferedSocketClient bsc = new BufferedSocketClient();      }  } 

This client uses the same logic flow as the LoopingSocketClient example, except that it uses different classes to handle the input and the output. The BufferedReader class provides a more efficient way to read characters. Unbuffered readers, like the InputStreamReader class, tend to be inefficient because they tend to trigger an actual read to the underlying stream every time a read method is invoked. BufferedReaders, on the other hand, read larger amounts of data when, a read method call is made. It buffers the extra data that was retrieved and hands it over to the program if and when it is requested by a subsequent read method call.

 BufferedReader br =  new BufferedReader(            new InputStreamReader(socket1.getInputStream())); 

The PrintWriter class prints objects to an output stream in text form. The second parameter indicates that we want autoflushing to occur whenever a println() method is invoked.

 PrintWriter pw =  new PrintWriter(socket1.getOutputStream(), true); 

The PrintWriter uses the println() method to place the String into the stream in text form.

 str = "initialize";  pw.println(str); 

The BufferedReader class uses the readLine() method to get data from the stream. Notice that this method places the data directly into a String object and that no explicit casting had to be done by the programmer.

 while ((str = br.readLine()) != null)  {      System.out.println(str);      pw.println("bye");      if (str.equals("bye bye"))          break; 

The server portion of this example also needs to have its ObjectInputStream and ObjectOutputStream classes replaced by the BufferedReader and the PrintWriter classes. Listing 20.11 shows this class.

Listing 20.11 The BufferedSocketServer.java File
 /*   * BufferedSocketServer.java   *   * Created on October 2, 2002, 5:24 PM   */  package ch20;  import java.net.*;  import java.io.*;  /**   *   * @author  Stephen Potts   */  public class BufferedSocketServer  {      ServerSocket servSocket;      Socket fromClientSocket;      int cTosPortNumber = 1777;      String str;      /** Creates a new instance of BufferedSocketServer */      public BufferedSocketServer()      {          // Create ServerSocket to listen for connections          try          {              servSocket = new ServerSocket(cTosPortNumber);              // Wait for client to connnect, then get Socket              System.out.println("ServerSocket created");              System.out.println("Waiting for a connection on " +              cTosPortNumber);              fromClientSocket = servSocket.accept();              System.out.println("fromClientSocket accepted");              PrintWriter pw =              new PrintWriter(fromClientSocket.getOutputStream(), true);              BufferedReader br = new BufferedReader(                new InputStreamReader(fromClientSocket.getInputStream()));               while ((str = br.readLine()) != null)               {                  System.out.println("The message from client is *** " +                                                                    str);                  if (str.equals("bye"))                  {                      pw.println("bye bye");                      break;                  }                  else                  {                      str = "Server returns " + str;                      pw.println(str);                  }              }              pw.close();              br.close();              // Close Sockets              fromClientSocket.close();          } catch (Exception e)          {              System.out.println("Exception " + e);          }      }      public static void main(String args[])      {          BufferedSocketServer bss = new BufferedSocketServer();      }  } 

We obtain a handle to the socket in exactly the same way as before.

             fromClientSocket = servSocket.accept();              System.out.println("fromClientSocket accepted");  The PrintWriter object is used on the server side also.              PrintWriter pw =              new PrintWriter(fromClientSocket.getOutputStream(), true);  

The BufferedReader is used to communicate back to the client also. Notice that Sockets are bidirectional, allowing a program to send information back using the same socket that it is reading from.

 BufferedReader br = new BufferedReader(    new InputStreamReader(fromClientSocket.getInputStream())); 

We use the readLine() method without having to perform an explicit cast and place the result in a String object.

 while ((str = br.readLine()) != null)  {      System.out.println("The message from client is *** " +                                                        str); 

We also use the println() method to place data onto the socket.

     str = "Server returns " + str;      pw.println(str);  } 

You start the BufferedSocketServer first, and then the BufferedSocketClient. The output from the client is shown here:

 Server returns initialize  bye bye 

The output from the server is shown here:

 ServerSocket created  Waiting for a connection on 1777  fromClientSocket accepted  The message from client is *** initialize  The message from client is *** bye 

Notice that the output from running this program is identical to the output we received when we ran the ObjectStream versions of the same program. This suggests that both approaches are valid, and that your decision should be based on the kind of data that you are sending, and what the normal volume of data is.


       
    Top
     



    Java 2 Primer Plus
    Java 2 Primer Plus
    ISBN: 0672324156
    EAN: 2147483647
    Year: 2001
    Pages: 332

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