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

DataInputStream can lose data when reading from SocketInputStream

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P3 P3
    • None
    • 1.3.0
    • core-libs
    • generic
    • generic



      Name: boT120536 Date: 01/22/2001


      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
      Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

      When a DataInputStream is layered on top of a SocketInputStream (or any other
      input stream which may generate a restartable exception such as an
      InterruptedIOException, the data input stream may lose data.

      Operations such as readInt, readFully, readUTF, etc. all perform multiple read
      calls to the underlying stream, and if any except the first call takes an
      InterruptedIOException, say due to a socket timeout, the partial data already
      read is discarded.

      The following examples demonstrate the problem. The transmitter sends a series
      of integer values using a DataOutputStream layered on a stream designed to get
      maximum packet fragmentation (ie. each byte should be sent in its own packet)
      with a delay between packets to simulate line delays such as TCP
      retransmissions. The receiver tries to read integers from a DataInputStream
      layered over a stream to monitor the number of characters actually read from
      the socket, with a socket timeout set on the socket. When the two programs are
      run, the transmitter sends its data, and the receiver reads data from the
      stream and delviers nothing to the caller.

      I consider this to be potentially very serious as it corrupts data, and
      underlies many other things such as ObjectInputStream, etc.

      Note - this may be the cause of some of the problems reported in Bug Id 4032593

      DataRecv.java:

      package com.hotstarttech.test;

      import java.io.*;
      import java.net.*;

      public class DataRecv {

          public static void main(String[] args) {
              try {
                  ServerSocket l = new ServerSocket(10000);
                  Socket s = l.accept();
                  InputStream str = s.getInputStream();
                  MonitorInputStream monitor = new MonitorInputStream(str);
                  DataInputStream data = new DataInputStream(monitor);

                  s.setSoTimeout(100);

                  System.out.println ("Connected...");

                  for (int i = 0 ; i < 100 ; i++) {
                      try {
                          int value = data.readInt();
                          System.out.println ("read " + value);
                      } catch (InterruptedIOException ex) {
                          System.err.println("interrupted");
                      }
                  }

                  System.out.println("Read " + monitor.getCount() + " bytes");
                  data.close();
                  s.close();
                  l.close();;
              } catch (IOException ex) {
                  System.err.println ("IO Exception - " + ex);
                  ex.printStackTrace();
              }
          }
      }

      class MonitorInputStream extends FilterInputStream {
          int count = 0;

          public MonitorInputStream (InputStream str) {
              super(str);
          }

          public int read() throws IOException {
              int c = in.read();
              count++;
              return c;
          }

          public int read(byte[] buffer, int off, int len) throws IOException {
              int nread = in.read(buffer, off, len);
              count += nread;
              return nread;
          }

          public int getCount() {
              return count;
          }
      }


      DataXmit.java:

      package com.hotstarttech.test;

      import java.net.*;
      import java.io.*;

      public class DataXmit {

          public static void main(String[] args) {
              try {
                  Socket s = new Socket("localhost", 10000);
                  OutputStream str = s.getOutputStream();
                  BrokenOutputStream broke = new BrokenOutputStream(str);
                  DataOutputStream data = new DataOutputStream(broke);

                  s.setTcpNoDelay(true);

                  for (int i = 0 ; i < 50 ; i++) {
                      data.writeInt(i);
                      System.out.println ("Sent " + i);
                  }

                  data.close();
              } catch (IOException ex) {
                  System.err.println ("IO Exception - " + ex);
                  ex.printStackTrace();
              }
          }
      }

      // this stream should cause maximum fragmentation of the output stream by
      // inserting delays and writing and flushing single bytes
      class BrokenOutputStream extends FilterOutputStream {
          public BrokenOutputStream(OutputStream s) {
              super(s);
          }

          public void write(int b) throws IOException {
              try {
                  Thread.sleep(110);
              } catch (InterruptedException ex) {}
              out.write(b);
              out.flush();
          }
      }
      (Review ID: 113677)
      ======================================================================

            mmcclosksunw Michael Mccloskey (Inactive)
            bonealsunw Bret O'neal (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: