Mayank S
asked on
Socket input-stream
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.
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.
ASKER
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.toSt ring ( encoding ) to get the String contents. However, when the connection is broken from the other side, why is it not notified~!
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.toSt
>>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.getOutputStr eam(), true);
>>why is it not notified~!
Not sure
Well i would begin by, as you yourself have said recently, by doing the following:
PrintWriter out = new PrintWriter(s.getOutputStr
>>why is it not notified~!
Not sure
ASKER
>> 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 () ) ;
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 () ) ;
>>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
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
ASKER
>> 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 () ?
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 () ?
>>and flush regularly
(if not on auto-flush)
>>I assume on the other side, it still remains as inputStream.read () ?
Yes
(if not on auto-flush)
>>I assume on the other side, it still remains as inputStream.read () ?
Yes
ASKER
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 ?
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 ?
ASKER
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.
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
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
ASKER
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?
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?
ASKER
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?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
also
byte[] bfr = new byte[ 1024 ] ;
should be outside the while loop
byte[] bfr = new byte[ 1024 ] ;
should be outside the while loop
ASKER
Tim/ Webstorm - actually this was a .NET application where we had used NetworkStream.Read () and NetworkStream.DataAvailabl e. 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.
>> 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
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
ASKER
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Any other approaches you can suggest?
>> You simply read the stream to EOF
Meaning till -1?
>> You simply read the stream to EOF
Meaning till -1?
Yes
ASKER
Lesson learnt: don't use available () ;-)
I think we should make this change in the .NET version too - instead of using networkStream.DataAvailabl e, we should check for -1. It always worked in .NET for a year though :-O
I think we should make this change in the .NET version too - instead of using networkStream.DataAvailabl
:-)
Maybe - i do it exactly the same way in .NET
Maybe - i do it exactly the same way in .NET
ASKER
Didn't know that you were doing hands-on with .NET too. Thank God I am almost out of it ;)
Well i don't do much - i'm not into M$ ;-)
ASKER
Good for us ;-)
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