Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Socket input-stream

Posted on 2006-05-03
26
Medium Priority
?
682 Views
Last Modified: 2008-02-07
Folks,

I'm facing a strange problem reading from the input-stream of a socket. If the socket on the other side is closed, inputStream.read () does not throw an IOException but simply waits, or sometimes reads a "?"

Anybody faced this before? Is this something new with Java 5? I'm running it on Windows 2003 Enterprise Server and the client for the server is also built in Java. I send bytes using outputStream.write () and later flush () it. On the server-side, I receive using inputStream.read (). If I deliberately close the client, the server thread either hangs, or sometimes reads some special character. The encoding used for data on both sides is the same (either UTF-8 or ASCII).

When I do a netstat, I can see that port shows me a TIME_WAIT. It should not be shown~! It should be disconnected.

Thanks,
Mayank.
0
Comment
Question by:Mayank S
  • 13
  • 9
  • 2
  • +1
26 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 16597446
>>or sometimes reads some special character.

That shouldn't be happening. Sounds like buffers are not getting flushed. As for the 'special character', it's sounding like an encoding problem. What data are you sending?

>>I can see that port shows me a TIME_WAIT. It should not be shown~! It should be disconnected.

Actually TIME_WAIT is normal, but i'm not sure why
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16603155
Yeah the TIME_WAIT is normal as per http://support.microsoft.com/default.aspx?scid=kb;EN-US;q137984

Anyway, I tried with both encodings ASCII and UTF-8. While sending, I did outputStream.write ( dataString.getBytes ( encoding ) ) ; While receiving, I read the bytes into a ByteArrayOutputStream using inputStream.read (), then used byteArrayOutputStream.toString ( encoding ) to get the String contents. However, when the connection is broken from the other side, why is it not notified~!
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16603338
>>I did outputStream.write ( dataString.getBytes ( encoding ) ) ;

Well i would begin by, as you yourself have said recently, by doing the following:

PrintWriter out = new PrintWriter(s.getOutputStream(), true);

>>why is it not notified~!

Not sure
0
Technology Partners: 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 30

Author Comment

by:Mayank S
ID: 16603565
>> Well i would begin by, as you yourself have said recently, by doing the following:

I knew this suggestion will come up but the problem is that the String will itself contain multiple new-lines (its an XML file), so I wanted to send them byte-by-byte, and receive at the other side byte-by-byte (not using bufferedReader.readLine () ) ;
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16605028
>>will itself contain multiple new-lines (its an XML file)

Where are the new lines? If they're between nodes as opposed to node contents, then that's actually view-specific as opposed to model-specific and as such, not important

If the latter, just call print as opposed to println and flush regularly
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16605059
>> If they're between nodes as opposed to node contents

They are between nodes. I will try with print () and let you know. I assume on the other side, it still remains as inputStream.read () ?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16605284
>>and flush regularly

(if not on auto-flush)


>>I assume on the other side, it still remains as inputStream.read () ?

Yes      
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16605786
Same output. The server has got:

while ( true )
{
  ByteArrayOutputStream bs = new ByteArrayOutputStream () ;
  do
    bs.write ( is.read () ) ;
  while ( is.available () > 0 ) ;
  bs.flush () ;
  System.out.println ( bs.toString ( "ASCII" ) ) ;
}

is.read () returns everything correct initially. But then the loop runs again and waits at is.read (), then if the client disconnects, is.read () returns me a ? (some special character). It should throw an exception, right? I tried with all combinations like commenting/ uncommenting out.flush ()/ out.close () on the other side. If I use the platform-default encoding (simply bs.toString ()), I see that its just a blank space (rather nothing) being printed instead of the ?
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16638573
BTW, sometimes this also returns a part of the data instead of the entire data. That shouldn't happen, right? That happens only on XP but not on Windows 2003.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16640697
That server code isn't right in several respects

a. bs is written to irrespective of the value returned by is.read
b. testing on available is unreliable
c. creating a BAOS in a potentially tight loop is dubious - just reuse the same one
d. if you're reading strings you would be better using Reader/Writer
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16645092
I'm using strings but I don't have an end-character like new-line or something. So I don't want to use readLine (), etc because the data I'm reading might have multiple new-lines itself. That's why everything that is.read () returns is written into bs.

Creating the bs/ reusing is ok - I can do that but I don't think that will cause a functionality error.

However, you say that testing on available () is unreliable - then how else do I check if there is still some data in the input-stream? That is what the method is for, right?
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16697106
Any ideas on what is the better approach to read 'as long as there is data in the stream' without using a length or an end-character kind of approach?
0
 
LVL 35

Assisted Solution

by:TimYates
TimYates earned 200 total points
ID: 16706506
Why not try the "normal" way of reading the stream?

while ( true )
{
  ByteArrayOutputStream bs = new ByteArrayOutputStream () ;
  byte[] bfr = new byte[ 1024 ] ;
  int cnt = 0 ;
  while( ( cnt = is.read( bfr, 0, bfr.length ) ) > 0 )
  {
    bs.write( bfr, 0, cnt ) ;
  }
  System.out.println ( bs.toString ( "ASCII" ) ) ;
}
0
 
LVL 13

Assisted Solution

by:Webstorm
Webstorm earned 100 total points
ID: 16707012
Hi mayankeagle,

The problem with read() method, is it will block until a byte is available.
You should use read(byte[],int,int) or read(byte[]) (as in TimYates 's suggestion) which will not block, because returning the number of read bytes.

From TimYates example, corrected :

...
  int cnt = 0 ;
  while( ( cnt = is.read( bfr, 0, bfr.length ) ) > 0 )
  {
    bs.write( bfr, 0, cnt ) ;
  }
  if (cnt<0) break; // end of stream (socket is closed)
...
0
 
LVL 13

Expert Comment

by:Webstorm
ID: 16707017
also
  byte[] bfr = new byte[ 1024 ] ;
should be outside the while loop
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16707047
Tim/ Webstorm - actually this was a .NET application where we had used NetworkStream.Read () and NetworkStream.DataAvailable. That worked fine in every run. While writing the same application in Java, the developers made some equivalent changes in the code (like changed it to read () and available ()). I will make these changes to read ( byte[], int, int) and see if it gets better.
0
 
LVL 35

Expert Comment

by:TimYates
ID: 16707080
>> which will not block

Yes it will...  It's a blocking IO call...

So the break isn't needed...

(as far as I know...  I may well be wrong with this) ;-)

Tim
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16758095
I'm beginning to think that its a problem with my system. For some reason, the while loop above also works for some cases and just hangs in some cases.
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 200 total points
ID: 16758528
>>
However, you say that testing on available () is unreliable - then how else do I check if there is still some data in the input-stream?
>>

You simply read the stream to EOF

>> That is what the method is for, right?

No - not really. It tests whether data can be read *without blocking*. It could return false while there are still data
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16758727
Any other approaches you can suggest?

>> You simply read the stream to EOF

Meaning till -1?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16758733
Yes
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16766370
Lesson learnt: don't use available () ;-)

I think we should make this change in the .NET version too - instead of using networkStream.DataAvailable, we should check for -1. It always worked in .NET for a year though :-O
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16767512
:-)

Maybe - i do it exactly the same way in .NET
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16767538
Didn't know that you were doing hands-on with .NET too. Thank God I am almost out of it ;)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 16767554
Well i don't do much - i'm not into M$ ;-)
0
 
LVL 30

Author Comment

by:Mayank S
ID: 16767584
Good for us ;-)
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying 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

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…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses
Course of the Month10 days, 8 hours left to enroll

572 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