Solved

timout on readLine

Posted on 2000-04-12
16
406 Views
Last Modified: 2008-03-06
Hello,
   How would you write java code to timeout on a call to BufferedReader.ReadLine() ?

I would like to make the call and if nothing comes back in a minute then terminiate the read.


0
Comment
Question by:calvinrsmith
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +2
16 Comments
 
LVL 16

Accepted Solution

by:
imladris earned 9 total points
ID: 2708394
Do the readLine in a separate thread. Then, when the main thread has waited long enough, it can carry on. It may want to kill the "read" thread. This can be done with the stop method, or (since stop has been deprecated in 1.2) by calling interrupt and the read thread catching the InterruptedException.
0
 
LVL 5

Expert Comment

by:mbormann
ID: 2708897
readymade code,pls look and use it...
Notice that this code is JDK1.2 compliant ,I am closing the underlying InputStream in ,so

if you have to close the socket read/write
you have to close() the underlying input/output stream.
Get a reference like
InputStream in=sock.getInputStream();
Use in program like
BufferedReader buff = new BufferedReader(new InputStreamReader(sock.getInputStream()));

The reason is that both read() and close() are synchronized in
Wrapper classes like BufferedReader & BufferedInputStream in JDK 1.2
& up ,so this above program will only work in JDK 1.1.

Translated into simpler terms when you call close() ,it will block
forever.

So use

in.close() instead of buff.close()

public class AsyncReadBuffer
{
    private StringBuffer result;

    public AsyncReadBuffer()
    {
        result = new StringBuffer(500);
    }

    //Get the string already read from the socket so far.
    //This method is used by the Applet or external thread
    //to obtain the data in a synchronous manner.
    public synchronized String getResult()
    {
        String retval = result.toString();
        result.setLength(0);
        return retval;
    }

    //Put new data into the buffer to be returned
    //by the getResult method
    public synchronized void update(char c)
    {
        result.append(c);
    }

public synchronized void update(String s)
    {
        result.append(s);
    }
}


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

public class ClientHandler extends Thread
{
    private InputStream in;
    private BufferedReader buff;
    private Socket sock;
    private AsyncReadBuffer aReader;
    private boolean isDone = false;
    private Object lock = new Object();
private int timeout;
private boolean isReadLineMode=false;

    class ClientHandlerThread extends Thread
    {
        public void run()
        {
            String s;
int c;
            try
            {
if(isReadLineMode)
{
while ((s = buff.readLine()) != null)
    aReader.update(s);
}
else
{
while ((c = buff.read()) != -1)
    aReader.update((char)c);
}
}
            catch (Exception e)
            {}

            isDone = true;
            synchronized(lock)
            {
                lock.notify();
            }
        }
    }

    public ClientHandler(AsyncReadBuffer a, Socket s,int t,boolean isReadLine)throws Exception
    {
this.aReader=a;
        this.sock=s;
this.isReadLineMode=isReadLine;
if(t<0 || t==Integer.MAX_VALUE)
throw new Exception("Specify correct timeout value");
this.timeout=t;
    }

    public void run()
    {
try
{
    in=sock.getInputStream();
    this.buff = new BufferedReader(new InputStreamReader(in));
    Thread t = new ClientHandlerThread();
    t.start();
    synchronized(lock)
    {
        while (!isDone)
        {
            try
            {
                lock.wait(this.timeout);
            }
            catch (InterruptedException ie)
            {
                isDone = true;
                try
                {
                    t.interrupt();
                    this.in.close();this.in=null;
                    this.sock.close();this.sock=null;
                }
                catch (Exception e)
                {}
            }
        }
    }
}
catch(Throwable t)
{
System.out.println("Caught Exception during run() in timeout main thread");
t.printStackTrace();
}
}
}
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2709276
I've been working on trying to find a non-threaded solution. After a good bit of experimentation, I determined that the code appearing below SHOULD work. Unfortunately, it does not work on win32 systems because the BufferedReader implementation -- at least in jdk1.3rc2 -- does not correctly (or at least to my liking) implement the semantics of readLine().

The API docs for readLine state: "Read a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed." This gives one (one being me in this case) the impression that the entire line-termination sequence will consumed. On win32 systems, line-termination is "\r\n", two characters. Unfortunately, the implementation does not consume both characters immediately. It finds the carriage return but leaves the newline in the buffer. As a result, ready() returns true but the subsequent read blocks when the only content in the buffer is the second half of the win32 line termination sequence.

This same problem does not appear to plague the InputStreamReader so it would be possible to use the technique implemented below with that reader. Perhaps I should provide a readLine() implementation for InputStreamReader? If anyone is interested, let me know.

Here is the correct but, on win32 systems, non-working code:

---------- TimedReader.java ----------
import java.io.InputStreamReader;
//import java.io.BufferedReader;
import java.io.Reader;
import java.io.IOException;

public class TimedReader {
    public static void main(String[] args) {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader in = new BufferedReader(isr);
        while (true) {
            try {
                System.out.print("Enter a String: ");
                if (ready(in, 5000)) {
                    String s = in.readLine();
                } else {
                    System.out.println("timeout");
                }
            } catch (IOException e) {
                // ignore until we know what to do
            }
        }
    }

    public static boolean ready(Reader in, long timeout) throws IOException {
        while (true) {
            long now = System.currentTimeMillis();
            try {
                while (in.ready() == false && timeout > 0) {
                    Thread.sleep(100);
                    timeout -= 100;
                }
                return in.ready();
            } catch (IOException e) {
                throw e;
            } catch (Exception e) {
                // ignore
            } finally {
                // adjust timer by length of last nap
                timeout -= System.currentTimeMillis() - now;
            }
        }
    }
}
---------- end ----------

Since you didn't state your platform, this code may work just fine for you. I hope so. I have a modified version of BufferedReader.java which fixes the problem -- but I don't know how robust that fix is or whether it would prevent this scenario in all circumstances.

Best regards,
Jim Cakalic
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Expert Comment

by:mbormann
ID: 2709345
I think Jim ur code would work on JDK 1.2.2 ,what do you think ?

Have they introduced a bug in JDK1.3?
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2709399
Amit, if you have a previous version of the JDK, would you care to give it a try? I only have 1.3 at my disposal presently.

You may be right, though, about changed behavior. In Harold's Java I/O book from O'Reilly, he states that BufferedReader.readLine() has "the potential to hang on a long carriage return that ends the stream. This problem is especially acute on networked connections, where readLine() should never be used." Browsing the bug database at JDC, I found quite a few complaints about the hanging carriage return problem. Perhaps they introduced a 'fix' in 1.3. Again, I don't have what I need to check this out so any help would be appreciated.

Jim
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2709420
Just realized that, since I have JBuilder 3 I have jdk1.2.2 installed. Found the source and the code for BufferedReader.readLine() has been changed. Compiled and tested the old code with my program above and it works!!!!! I'm not going crazy after all.

Guess I'll post something on the bug parade. Doubt if it will get into jdk1.3, though. They're already in rc2.

Jim
0
 
LVL 1

Author Comment

by:calvinrsmith
ID: 2709529
  I'm still using JDK1.1.8 I'll give the above ideas a try and let you know what I find.  
0
 
LVL 5

Expert Comment

by:mbormann
ID: 2709574
calvinrsmith,
Oops sorry I realized that I had cut-pasted wrong explanation in my long comment above. But the code is perfect. You can use that too .

But I think u would be happy with Jim's solution.
:)

Jim , it works. And I will post this code sometime later today to the question from which I cut-pasted the original code.

Cheers fellows
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2710487
Those guys at Sun are fast. I submitted a bug report this afternoon and already got back a reply that it is considered to be a new defect and has been assigned id 4329985. It may not show up on the bug parade for several days according to the email I received.
0
 
LVL 5

Expert Comment

by:mbormann
ID: 2712351
Wow ! Yes I also reported a 'bug' but it was submitted just sometime b4 I sent them a mail and they gave the same reply.

They work round the clock is what I think,must be having guys all over the world in differect time zones.

Cheers Jim
0
 
LVL 1

Author Comment

by:calvinrsmith
ID: 2713884
jim_cakalic,
  I tested your code with jdk1.1.8 on win98 and found that in.ready() always returns true, even if your ready function just started.
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2751117
Calvin, I don't know what to tell you about this other than jdk1.1.8 is notoriously buggy. Running in win95 or win98 doesn't help. Is it possible for you to use a more recent release of the jdk? Any of the 1.2 releases would be better. Frankly, many suggestions I have seen are to stick with 1.1.7 if 1.2 is not an option.

I've got IBM's port of 1.1.8 to AIX that I can look at. Barring that, I'd have to download and unpack (if not install) another jdk version. Painful but I'd consider doing it.

Anybody else have any ideas?
Jim
0
 

Expert Comment

by:leach072899
ID: 3965392
I checked this code on VisualAge with JDK 1.1.7 - works perfectly.
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 3968479
Hi, leach.

This one has certainly been around for awhile, hasn't it? Thanks for testing it. I figured Calvin had abandoned the question. Looked on the JDC and the bug has 21 votes but apparently never got fixed in the 1.3 release.

Jim
0
 

Expert Comment

by:leach072899
ID: 3968641
Hi Jim,
Well it was about something i was looking for.
Moving to Java 2 (any version) looks a bit farther then i want it to be, for us VisualAge users.
My problem is a bit more trickier so i opened another question on it - see if you can answer.

lee
0
 

Expert Comment

by:leach072899
ID: 3997345
I said it runs with JDK 1.1.7 - i must retrackt that.
At least on the IBM implementation the timeout works perfectly when needed - but when all is well - using the timeout after the connection was closed (from either end) will result in a timeout condition. And there is no way (that i found yet) to distinguish the two cases: timeout and connection closed.

lee
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
eclipse apache tomcat admin console 52 156
Java Restore security prompts not working 10 140
jsp error 6 46
Delete .class files at every compile 4 22
INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
This video teaches viewers about errors in exception handling.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question