Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4643323

BufferedOutputStream Does Not Always Flush When Used with Socket

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P3 P3
    • None
    • 1.4.0
    • core-libs
    • x86
    • windows_2000



      Name: nt126004 Date: 02/26/2002


      FULL PRODUCT VERSION :
      java version "1.4.0-rc"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b91)
      Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]
      Service Pack #2


      A DESCRIPTION OF THE PROBLEM :
      There's a problem when a BufferedOutputStream is used to
      wrap the OutputStream returned from a Socket. When I
      say "wrap the OutputStream", of course, I mean something
      like this:

      BufferedOutputStream bos = new BufferedOutputStream
      (socket.getOutputStream());

      The problem is that the BufferedOutputStream is not always
      flushed correctly. There are two cases I've found when this
      problem occurs:

      1. If the InputStream returned from the Socket is closed
      before the BufferedOutputStream, the BufferedOutputStream
      is not flushed properly.

      2. If the Socket itself is closed before the
      BufferedOutputStream, the BufferedOutputStream is not
      flushed properly.

      I've included a sample program that illustrates case #1,
      above. The sample program writes 1,000 bytes to the
      BufferedOutputStream but not all of them are received by
      the client.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Set up a ServerSocket.
      2. Retrieve a Socket from the ServerSocket.
      3. Wrap the Socket's OutputStream with a
      BufferedOutputStream.
      4. Write a few thousand bytes to the BufferedOutputStream.
      5. Close the Socket's InputStream (or close the Socket
      itself).
      6. Close the BufferedOutputStream.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected
      --------
      I would expect all the bytes written to the
      BufferedOutputStream to be sent to the client, regardless
      of whether the BufferedOutputStream is closed before or
      after the InputStream or the Socket.

      The order of stream closing should *not* affect whether or
      not the BufferedOutputStream is properly fushed. I *SHOULD*
      be able to either close the InputStream *OR* close the
      Socket itself and know that the BufferedOutputStream will
      be properly fushed.


      Actual
      ------
      If the InputStream returned from the Socket is closed
      before the BufferedOutputStream (which wraps the
      OutputStream returned from the Socket), then the
      BufferedOutputStream is not properly flushed.

      If the Socket itself is closed before the
      BufferedOutputStream (which wraps the OutputStream returned
      from the Socket), then the BufferedOutputStream is not
      properly flushed.



      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.*;
      import java.net.*;

      class Tester {
        public static void main(String[] args) throws Exception {
          // Set up the server
          new Thread() {
            public void run() {
              ServerSocket ss = null;
              Socket s = null;
              OutputStream bos = null;
              InputStream is = null;

              try {
                ss = new ServerSocket(4444);

                s = ss.accept();

                // Get the InputStream and OutputStream from the Socket.
                is = s.getInputStream();
                bos = new BufferedOutputStream(s.getOutputStream());

                int BYTES_TO_GENERATE = 1000;

                // Write the bytes....
                for(int i = 0; i < BYTES_TO_GENERATE; ++i)
                  bos.write(i);
              } catch(Exception e) {
                System.err.println("There was an exception in the server code: " + e);
                e.printStackTrace();
              } finally {
                try {
                  // Close the server socket.
                  ss.close();

                  // The BufferedOutputStream is not properly flushed in these two
                  // situations:
                  //
                  // 1. Closing the InputStream before the BuffereredOutputStream.
                  // 2. Closing the Socket before the BufferedOutputStream.
                  //
                  // If we close the BufferedOutputStream before
                  // closing the InputStream or clsoing the Socket *OR* we simply
                  // use an OutputStream rather than a BufferedOutputStream, this
                  // problem goes away.
                  is.close(); //close InputStream, comment this for correct behavior
                  bos.close(); //close the BufferedOutputStream
                  s.close(); //close the Socket
                } catch(Exception e) {
                  System.err.println("Exception closing something..." + e);
                }
              }
            } // run()
          }.start(); // start the server thread


          // 10KB Buffer to read in the data from the server.
          byte[] b = new byte[10 * 1024];

          // Open a connection to the server
          Socket s = new Socket("localhost", 4444);

          InputStream is = s.getInputStream();

          int bytesReadSoFar = 0;
          int bytesRead = 0;
          while((bytesRead = is.read(b)) != -1)
            bytesReadSoFar += bytesRead;

          System.out.println("The client read a total of " + bytesReadSoFar + "
      bytes.");

          is.close();
          s.close();
        } // main()
      } // Tester


      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      If using a BufferedOutputStream to wrap the OutputStream
      returned from the Socket, be sure to close the
      BufferedOutputStream *BEFORE* closing either the
      InputStream returned from the Socket or the Socket itself.
      (Review ID: 139479)
      ======================================================================

            alanb Alan Bateman
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: