How can I detect a carriage return using java.net

A

Angus

Hello

I have code a bit like this:

BufferedReader bis = new BufferedReader(new
InputStreamReader(tserverSocket.getInputStream()));

// Here I write some data - getting a response - some lines of text returned

boolean more = true;
while(more)
{
String line = bis.readLine();
if (line == null)
more = false;
else
System.out.println(line);
}

But code never gets out of while loop.

I assumed when there was no more input it would return null, so more would
be set to false and it would exit loop.

I want to test for a carriage return. (I know text is in ASCII format, and
I know end of each line has a carriange return and line feed.

So I tried doing this:

if (line.indexOf("\n") != -1)
{
break;
}

But it didn't seem to find \n . How should I test for a carriage return?

Angus
 
J

java

Angus,

BufferedReader does return null when there is more data to read.
However, when dealing with a socket (based on the "tserverSocket"
variable name), its possible that if the connection is still active
that the empty string might be what is being returned. The
BufferedReader.readLine() method automatically strips off the carriage
return so trying to match based on that will never be true.

For example, if the stream sends "one\ntwo\nthree\n" The first
invocation of readLine() would return "one", etc.

I think I need a little more information about the tserverSocket to
assist more on this.


kavaj
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Angus said:
boolean more = true;
while(more)
{
String line = bis.readLine();
if (line == null)
more = false;
else
System.out.println(line);
}

But code never gets out of while loop.

I assumed when there was no more input it would return null, so more would
be set to false and it would exit loop.

If you want to read one line then use:

String line = bis.readLine();


If you want to read multiple lines then your code
should work even though:

String line;
while((line = bis.readLine()) != null) {
....
}

is the most common way of doing it.

Note that readLine first return null (EOF) when the socket is
closed in the other end.

Arne
 
G

Gordon Beaton

// Here I write some data - getting a response - some lines of text
// returned

boolean more = true;
while(more)
{
String line = bis.readLine();
if (line == null)
more = false;
else
System.out.println(line);
}

But code never gets out of while loop.

That's a complicated way of writing a simple loop. This is the idiom:

String line;
while ((line = bis.readLine()) != null) {
System.out.println(line);
}
I assumed when there was no more input it would return null, so more
would be set to false and it would exit loop.

It will, but "no more input" means "end of file". readLine() returns
null and the loop will exit when you reach EOF, i.e. when the remote
*closes* the connection. You won't reach EOF as long as the remote
keeps the connection open.
I want to test for a carriage return. (I know text is in ASCII
format, and I know end of each line has a carriange return and line
feed.

readLine() has already tested for newlines and removed them. Each line
it returns is exactly one whole line.

/gordon
 
A

Angus

Ah OK.

So what I really want to know is how do I know when server has finished
sending me data?

Eg my socket server sends out 1 to many lines of output. How do I know when
server has finished sending data? Is it possible?

Or does my server need to somehow send some data which indicates sending has
finished?

I have the source code for the server too so I can edit the the way the
server outputs data if necessary.

Angus
 
G

Gordon Beaton

So what I really want to know is how do I know when server has
finished sending me data?

Eg my socket server sends out 1 to many lines of output. How do I
know when server has finished sending data? Is it possible?

Or does my server need to somehow send some data which indicates
sending has finished?

Yes it's possible, but the solution depends on what happens later.

If you don't need to keep the connection open, then the server can
just close it and readLine() will return null, indicating EOF.

If you need to need continue communicating with the server, then the
server should send information the client can use to determine where
the end of the response is. One way is to precede the response with
the number of lines to expect so the client can count them. Another is
to send an extra, empty line ("") after the response (assuming that
can't occur within the response itself), or to mark the final line of
the response differently from the others in some way.

/gordon
 
R

Red Orchid

Message-ID: said:
Ah OK.

So what I really want to know is how do I know when server has finished
sending me data?

Eg my socket server sends out 1 to many lines of output. How do I know when
server has finished sending data? Is it possible?

Or does my server need to somehow send some data which indicates sending has
finished?

As I know as,
'null' do not necessarily indicate that server has finished
sending data. 'null' may be returned when unexpected
network error occurs (ex: unexpected connection close).

Therefore, communication protocol must have an ending
indicator.

For example,
With NNTP, a single period (".") on a line indicates the
end of sending data.

With HTTP, an empty line("") indicates it. (Or "Content-Length").

With a server that sends only one line to a client always,
"\r\n" will indicate it.

I think that you have to code a server that send out it.
 
M

Martin Gregorie

Gordon said:
If you don't need to keep the connection open, then the server can
just close it and readLine() will return null, indicating EOF.
With all due respect, I think that the connection should always be
opened and closed by the client: if the server closes the connection you
have no way of telling if the network broke, the server crashed or if it
was an intentional "end of dialog" closure.
the server should send information the client can use to determine where
the end of the response is. One way is to precede the response with
the number of lines to expect so the client can count them. Another is
to send an extra, empty line ("") after the response (assuming that
can't occur within the response itself), or to mark the final line of
the response differently from the others in some way.
A better way is to precede each message with its length, which should be
either a binary byte or (better) a fixed length character string, e.g.,

0012Message data

This way the receiver starts with a fixed length read to get the message
data length, translates it into an int and then reads that many bytes to
get the message. If either read gets the wrong number of bytes you know
there's a problem and you can take corrective action.

If both client and server send this type of message both can use the
same error checking and message decoding code with the addition that, if
the server receives a zero length message when its expecting a message
length it knows that the client has closed the connection.

I usually build messages this way, but assemble them from comma
separated fields. If the client always sends messages consisting of a
command and an associated value a message might look like:

0024,STORE,Text to be stored

While the reply from the server might look like

0004,OK,

or

0023,ERROR,The file is full

This format has the double advantage that its easy to decode and is
human-readable when it appears in debugging messages, etc.
 
E

EJP

BufferedReader does return null when there is more data to read.
However, when dealing with a socket (based on the "tserverSocket"
variable name), its possible that if the connection is still active
that the empty string might be what is being returned.

This makes no sense. A null will be returned when the other end closes
its socket. Anything else returned, including an empty string, is
returned because the other end wrote it, and for no other reason.
 
E

EJP

Martin said:
With all due respect, I think that the connection should always be
opened and closed by the client: if the server closes the connection you
have no way of telling if the network broke, the server crashed or if it
was an intentional "end of dialog" closure.

Except that an orderly close returns a null via readLine(), or -1 via
read(), or an EOFException via any other method, whereas a disorderly
close throws an IOException, or a SocketException, or possibly just
blocks forever.
 
E

EJP

Red said:
As I know as,
'null' do not necessarily indicate that server has finished
sending data. 'null' may be returned when unexpected
network error occurs (ex: unexpected connection close).

This is 100% incorrect.
 
G

Gordon Beaton

With all due respect, I think that the connection should always be
opened and closed by the client: if the server closes the connection
you have no way of telling if the network broke, the server crashed
or if it was an intentional "end of dialog" closure.

As EJP already pointed out there are other ways of determining those
things.

I wonder though why you want to favour the client. Isn't information
about the connection state equally useful at *both* ends of the
connection?

/gordon
 
M

Martin Gregorie

EJP said:
Except that an orderly close returns a null via readLine(), or -1 via
read(), or an EOFException via any other method, whereas a disorderly
close throws an IOException, or a SocketException, or possibly just
blocks forever.
>
If the server crashes when the client is expecting a reply, the client
will just get a null from readLine because, at the lowest level, the
reader can't distinguish an intentional close from a connection that
closes when the remote program crashes.

IIRC you'll only get the IOException if you try to write to a broken
connection or try to read it after you've already seen the close.
 
M

Martin Gregorie

Gordon said:
As EJP already pointed out there are other ways of determining those
things.

I wonder though why you want to favour the client. Isn't information
about the connection state equally useful at *both* ends of the
connection?
Yes, of course, but if you use the convention that only the client opens
and closes connections then:

- the client can treat any disconnection or i/o problem as an error.

- the server can always just clean up and wait for another
connection when it sees a disconnection. It also does the same
if sending a response fails but should also log the error.

If the server is stateless that's all it ever needs to do.

A stateful server is more complex because a disconnect is
only valid if its waiting for the start of a session. A disconnect
or i/o error at any other time is always an error.

I've designed complex, high performance, multi-process systems without
needing to use stateful message exchanges. These have used
request/response pairs with the client issuing the request. The overhead
of the positive response has never been a problem and it certainly makes
error recovery and process synchronization a lot easier.
 
R

Red Orchid

Message-ID: said:
This is 100% incorrect.


Let's assume that you have an external modem for networking.

Execute the class 'Test'.
If you turn off the modem in the middle of receiving data,
this code returns 'null', not an exception.

The 'null' do not indicate that a server has finished
sending data because the modem was turned off.


<code>
public class Test {

public static void main(String[] args) throws Exception {

process();
}

static void process() {
String url = "http://Your Server/Your Data File";
BufferedReader br = null;

try {
HttpURLConnection uc;

URL u = new URL(url);
uc = (HttpURLConnection) u.openConnection();

int code = uc.getResponseCode();

if (code != 200) {

System.out.println("Err Code: " + code);
return;
}

InputStreamReader ir;
InputStream in;

in = uc.getInputStream();
ir = new InputStreamReader(in);
br = new BufferedReader(ir);

while(true) {

if (br.readLine() == null) {

System.out.println("-< null >-");
break;
}
System.out.println("Receiving ...");
}
}
catch (Exception e) {

e.printStackTrace();
}
finally {
if (br != null) {
try {
br.close();
}
catch (Exception e) {
}
}
}
}
}

</code>
 
E

EJP

Martin said:
If the server crashes when the client is expecting a reply, the client
will just get a null from readLine because, at the lowest level, the
reader can't distinguish an intentional close from a connection that
closes when the remote program crashes.

At the lowest level the TCP stack will receive either nothing or an RST
from a disorderly close; it will receive a FIN from an orderly close.
 
E

EJP

Red said:
If you turn off the modem in the middle of receiving data,
this code returns 'null', not an exception.

Under the rules of TCP/IP you should get either nothing or an
IOException 'connection reset by peer'.
 
M

Martin Gregorie

EJP said:
At the lowest level the TCP stack will receive either nothing or an RST
from a disorderly close; it will receive a FIN from an orderly close.
>
Whether that difference is visible at application code level depends on
the stack implementation. On my kit, like all Unices, the difference
isn't visible and the behavior is not language dependent: C and Java do
exactly the same.
 
E

EJP

Martin said:
Whether that difference is visible at application code level depends on
the stack implementation. On my kit, like all Unices, the difference
isn't visible and the behavior is not language dependent: C and Java do
exactly the same.

There is no truth in this. At the 'C' level a read() or recv() or
recvmsg() will return 0 meaning EOF on receiving a FIN, and -1 with an
errno of ECONNRESET on receiving an RST. This is true both of Berkeley
Sockets and WINSOCK except for the WSA on the front of the names. At the
Java level a read() will return -1 on a clean EOF from a FIN, and throw
an IOException on a reset. Java's readLine(), readObject(), readXXX()
are all built on read(), and their behaviour on these conditions is
similarly well-defined.
 
M

Martin Gregorie

EJP said:
There is no truth in this. At the 'C' level a read() or recv() or
recvmsg() will return 0 meaning EOF on receiving a FIN, and -1 with an
errno of ECONNRESET on receiving an RST. This is true both of Berkeley
Sockets and WINSOCK except for the WSA on the front of the names.
>
Maybe so for Berkeley Sockets or WINSOCK, but that's not true for the
version in the Linux Fedora Core distribution. I'm well aware that
errors cause -1 to be returned, but the stack is not treating the
disconnection as an error.

Killing the remote process causes recv() to return zero, exactly the
same as if the remote process had closed the connection. This is not
speculation or derived from reading manpages: I just re-checked it by
running tests.

As I've seen this behavior in UNIX SVR4 systems as well as Linux its
obviously not uncommon.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top