public void close() throws IOException {
   synchronized (closeLock) {
     if (closed) {
       return;
     }
     socketOutput.close();
     socketInput.close();
     socket.close();
     closed = true;
   }
 }
  public byte[] readPacket() throws IOException {
    if (!isOpen()) {
      throw new ClosedConnectionException("connection is closed");
    }
    synchronized (receiveLock) {
      int b1, b2, b3, b4;

      // length
      try {
        b1 = socketInput.read();
        b2 = socketInput.read();
        b3 = socketInput.read();
        b4 = socketInput.read();
      } catch (IOException ioe) {
        if (!isOpen()) {
          throw new ClosedConnectionException("connection is closed");
        } else {
          throw ioe;
        }
      }

      // EOF
      if (b1 < 0) {
        return new byte[0];
      }

      if (b2 < 0 || b3 < 0 || b4 < 0) {
        throw new IOException("protocol error - premature EOF");
      }

      int len = ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0));

      if (len < 0) {
        throw new IOException("protocol error - invalid length");
      }

      byte b[] = new byte[len];
      b[0] = (byte) b1;
      b[1] = (byte) b2;
      b[2] = (byte) b3;
      b[3] = (byte) b4;

      int off = 4;
      len -= off;

      while (len > 0) {
        int count;
        try {
          count = socketInput.read(b, off, len);
        } catch (IOException ioe) {
          if (!isOpen()) {
            throw new ClosedConnectionException("connection is closed");
          } else {
            throw ioe;
          }
        }
        if (count < 0) {
          throw new IOException("protocol error - premature EOF");
        }
        len -= count;
        off += count;
      }

      return b;
    }
  }