Telnet: how to get all lines of response?

The telnet server I connect to responds with multiple text lines. My code to read the response is

final StringBuilder sb =new StringBuilder();

String s =null;

while ((s = br.readLine()) !=null){//wait to get next message from server

sb.append(s);

sb.append("\n");

}

result = sb.toString();

Unfortunately this code never returns as it reads all lines and the nextreadLine() blocks. Is there a way to detect the end of the last line?

[772 byte] By [MartinHilperta] at [2007-10-3 0:00:41]
# 1
The last line is the line delivered before the server closes the socket. The close is signalled to this code by readLine() returning null. Is that the line you mean?
ejpa at 2007-7-14 16:48:05 > top of Java-index,Archived Forums,Socket Programming...
# 2

Yes, but there is no 'null' line returning. E.g. when I issue a command to the server it responses with multiple answer lines but not a trailing 'null' line.The loop just halts at readLine() until I get the answer for my next command. So there is no way to tell if 1 line is the last line in a complete set of lines (that represent the complete answer of the server).

MartinHilperta at 2007-7-14 16:48:05 > top of Java-index,Archived Forums,Socket Programming...
# 3

>

> Unfortunately this code never returns as it reads all

> lines and the next readLine() blocks. Is there

> a way to detect the end of the last line?

The method readLine is supposed to block.

If you want different functionality then you are going to have to code it differently.

As a suggestion use a queue. The loop pushes stuff into the queue. Another thread pulls stuff from the queue.

Note that there is NO way to tell the 'end' of message without knowing looking at the content of the message and understanding all of the possible forms that that might take.

jschella at 2007-7-14 16:48:05 > top of Java-index,Archived Forums,Socket Programming...
# 4
Exactly. The null is returned when the other end has closed the socket, not when it has finished sending for the moment but may resume at another time.With the Telnet protocol probably your best solution is a shortish read timeout.
ejpa at 2007-7-14 16:48:05 > top of Java-index,Archived Forums,Socket Programming...
# 5

Best way to do this is to use a thread which gobbles as much as it can and then waits for more.

Instead of using a bufferedReader you could use my InfoFetcher class. Just create an InfoFetcher, add a listener and start it in a thread.

You are free to use and modify this code but please don't change the package or take credit for it as your own work

InfoFetcher.java

=============

package tjacobs.io;

import java.io.IOException;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.Iterator;

/**

* InfoFetcher is one of my most important classes. What is does is

* read from an input stream and report to registered listeners as it gets

* more information. This vastly simplifies the process of always re-writing

* the same code for reading from an input stream.

*

* I use this all over

*/

public class InfoFetcher implements Runnable {

public byte[] buf;

public InputStream in;

public int waitTime;

private ArrayList mListeners;

public int got = 0;

protected boolean mClearBufferFlag = false;

public InfoFetcher(InputStream in, byte[] buf, int waitTime) {

this.buf = buf;

this.in = in;

this.waitTime = waitTime;

}

public void addInputStreamListener(InputStreamListener fll) {

if (mListeners == null) {

mListeners = new ArrayList(2);

}

if (!mListeners.contains(fll)) {

mListeners.add(fll);

}

}

public void removeInputStreamListener(InputStreamListener fll) {

if (mListeners == null) {

return;

}

mListeners.remove(fll);

}

public byte[] readCompletely() {

run();

return buf;

}

public int got() {

return got;

}

public void run() {

if (waitTime > 0) {

TimeOut to = new TimeOut(waitTime);

Thread t = new Thread(to);

t.start();

}

int b;

try {

while ((b = in.read()) != -1) {

if (got + 1 > buf.length) {

buf = IOUtils.expandBuf(buf);

}

int start = got;

buf[got++] = (byte) b;

int available = in.available();

//System.out.println("got = " + got + " available = " + available + " buf.length = " + buf.length);

if (got + available > buf.length) {

buf = IOUtils.expandBuf(buf, Math.max(got + available, buf.length * 2));

}

got += in.read(buf, got, available);

signalListeners(false, start);

if (mClearBufferFlag) {

mClearBufferFlag = false;

got = 0;

}

}

} catch (IOException iox) {

throw new PartialReadException(got, buf.length);

} finally {

buf = IOUtils.trimBuf(buf, got);

signalListeners(true);

}

}

private void setClearBufferFlag(boolean status) {

mClearBufferFlag = status;

}

public void clearBuffer() {

setClearBufferFlag(true);

}

private void signalListeners(boolean over) {

signalListeners (over, 0);

}

private void signalListeners(boolean over, int start) {

if (mListeners != null) {

Iterator i = mListeners.iterator();

InputStreamEvent ev = new InputStreamEvent(got, buf, start);

//System.out.println("got: " + got + " buf = " + new String(buf, 0, 20));

while (i.hasNext()) {

InputStreamListener fll = (InputStreamListener) i.next();

if (over) {

fll.gotAll(ev);

} else {

fll.gotMore(ev);

}

}

}

}

}

InputStreamListener.java

====================

package tjacobs.io;

public interface InputStreamListener {

/**

* the new data retrieved is in the byte array from <i>start</i> to <i>totalBytesRetrieved</i> in the buffer

*/

public void gotMore(InputStreamEvent ev);

/**

* reading has finished. The entire contents read from the stream in

* in the buffer

*/

public void gotAll(InputStreamEvent ev);

}

InputStreamEvent.java

==================

package tjacobs.io;

/**

* The InputStreamEvent fired from the InfoFetcher

*

* the new data retrieved is from <i>start</i> to <i>totalBytesRetrieved</i> in the buffer

*/

public class InputStreamEvent {

public int totalBytesRetrieved;

public int start;

public byte buffer[];

public InputStreamEvent (int bytes, byte buf[]) {

this(bytes, buf, 0);

}

public InputStreamEvent (int bytes, byte buf[], int start) {

totalBytesRetrieved = bytes;

buffer = buf;

this.start = start;

}

public int getBytesRetrieved() {

return totalBytesRetrieved;

}

public int getStart() {

return start;

}

public byte[] getBytes() {

return buffer;

}

}

tjacobs01a at 2007-7-14 16:48:05 > top of Java-index,Archived Forums,Socket Programming...