Reading from a stream locks up

I have a program that listens to a port from a server that sends XML messages.  I listen and get the XML through a URL connection and then read in the stream like this below.   The problem is it seems to hang up when it gets the last tag from the XML.  By hang up, I mean when I step through the code at gets at clientStream.read after a couple iterations, my debugger stays at "stepping" forever and the program never ends until I terminated it.   What can be the problem?  I was trying to see if I can get the length of the incoming stream so I can tell the loop to run until it reaches the end, but I don't know how to do that.  Does somebody know?  Thanks.  I've tried different ways of reading the stream like reading it line by line but I get same result.

BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));            
BufferedReader inData = new BufferedReader(in);
InputStream clientStream = client.getInputStream();

while ((readstream=clientStream.read()) >= 0)
{
if ( readstream == 13 ) continue;
reqData[i] = (char)readstream;
i++;
}
MeroAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
>>so I can tell the loop to run until it reaches the end

Effectively you're doing that anway. And as it happens you're doing it in the most reliable way. Your code seems strange in some respects though. You should just get the stream once and read from it

while ((readstream=in.read()) >= 0)

Don't forget here:

>>if ( readstream == 13 ) continue;

that Windows also uses '\n' (ascii 10) for line feeds as part of its "\r\n" pair
0
MeroAuthor Commented:
thank for your reply,

going through it once doesn't get everything that is coming in.  In fact, part of the definition of the read() method in the JavaDoc is that it reads "some" bytes.
0
lwinkenbCommented:
>>I was trying to see if I can get the length of the incoming stream so I can tell the loop to run until it reaches the end, but I don't know how to do that.

You cant programmatically get the size of the data stream in the buffer, but you could maybe send the size of the incomming stream before you send the data.

Another thing you can try, is ending your stream with a byte value of 0.  That way your receiving program knows when it has recieved everything.

while ((readstream=clientStream.read()) >= 0)
{
if( readstream == 0 ) break;
if ( readstream == 13 ) continue;
reqData[i] = (char)readstream;
i++;
}
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

CEHJCommented:
>>going through it once doesn't get everything that is coming in.

What you should be doing, if the messages are arriving at arbitrary intervals, is reading it in a loop:
StringBuffer buffer = new StringBuffer();
String line = null;
BufferedReader in = null;

....


while (receiveMessages) {
  buffer.setLength(0);
  in = new BufferedReader(new InputStreamReader(client.getInputStream()));  
  while ((line=in.readLine()) != null) {
    (buffer.append(line);
  }
  String message = buffer.toString();
  in.close();
}
0
CEHJCommented:
>>Another thing you can try, is ending your stream with a byte value of 0.

That's not really an extensible implementation - for instance, it could not be used for 'binary' data.

A better way to know when you've finished reading, and to ensure the correct operation of the underlying TCP/IP, whatever is sending messages should get the output stream, use it, and close it for each message.
0
MeroAuthor Commented:
cehj, I tried your example, but now it locks up on the first try.  lwinken, readstream never gets to 0 before it locks up.  The xml is sent through a third party program which I don't have control over.  

I want to add that this is what happens before I start reading the data:
ss = new ServerSocket(6050);
Socket client =ss.accept();
ClientThread t = new ClientThread(client);
t.run();

t.run is where I have the code that is trying to read the incoming stream.  I'm pretty much listening to port 6050 to get this xml.  Any other ideas?   Thanks for all your suggestions.
0
objectsCommented:
First thing you should do is get rid of the following lines, they are not used:

BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));          
BufferedReader inData = new BufferedReader(in);
0
CEHJCommented:
I mentioned that before:

>>You should just get the stream once and read from it

Can you post ClientThread's run method?
0
objectsCommented:
Does the server close the connection once the xml message is sent?
If not then you'll get the behaviour you are seeing and you'll need some way to determine the end of the xml message.
0
objectsCommented:
>>You should just get the stream once and read from it

Getting the stream multiple times is fine.
It's the creation of Reader's that is the problem.
0
objectsCommented:
I mean may cause a problem.

The problem is more likely that the server is keeping the connection open after the xml has been sent.
0
CEHJCommented:
True, hence my earlier comment:

>>whatever is sending messages should get the output stream, use it, and close it for each message.
     
0
MeroAuthor Commented:
clientThread's run is pretty much what I posted above where its doing the reading but I'm posting it below.

I think the server is keeping the connection open.  I've e-mailed the vendor's support desk to see if they can tell me how the XML is sent through the server side.  But I am open to any suggestions or anything I can try in the meantime since I don't think they'll get back with me soon.  Thanks.


public ClientThread()
{
super();
}
ClientThread(Socket client)
{
this.client = client;
}

public void run()
{
BufferedReader in =
new BufferedReader(new InputStreamReader(client.getInputStream()));

BufferedReader inData = new BufferedReader(in);
InputStream clientStream = client.getInputStream();

while ((readstream=clientStream.read()) >= 0)
{
if ( readstream == 13 ) continue;
reqData[i] = (char)readstream;
i++;
}
}
0
objectsCommented:
>whatever is sending messages should get the output stream, use it, and close it for each message.

What the server does is up to it, it is up to the client to use it appropriately.

You need to find out from the server if they provide any markers to indicate the end of the xml message.

Another thing to try would be to pass the stream directly to your XML parser and let it detect the end of the message.

0
objectsCommented:
>  I'm pretty much listening to port 6050 to get this xml.

Why are you listening to 6050. This implies that the server is connecting to you.
Shouldn't you be connecting to the server.
0
CEHJCommented:
If you can't control what's happening at the server then just react to the end of the xml message instead of listening for EOF. This will presumably be the close of the root tag.
0
CEHJCommented:
In which case, replace

>>
 while ((line=in.readLine()) != null) {
    (buffer.append(line);
  }
>>

with

 while ((line=in.readLine()).indexOf(CLOSE_ROOT_TAG) < 0) {
    (buffer.append(line);
  }
0
objectsCommented:
> If you can't control what's happening at the server then just react to the end of
> the xml message instead of listening for EOF.

As I stated in my previous comment :D

> while ((line=in.readLine()).indexOf(CLOSE_ROOT_TAG) < 0) {

Not very safe
0
CEHJCommented:
>>Not very safe

There should be only one closing root tag, so I don't see why it isn't safe
0
objectsCommented:
a. There could be many.
b. Thats not the only reason it's unsafe

0
CEHJCommented:
a. The code will loop for the next one
b. Please elaborate
0
objectsCommented:
a. i don't think so
b. there are many
0
MeroAuthor Commented:
objects is right.   The XML coming in could be any XML message.  I can't check for the closing tag.   The server is connecting to my machine where I am running my code and listening.
0
objectsCommented:
Have you tried passing the stream directly to an XML parser.

What exactly do you need to do with the XML once you have recieved it?
0
MeroAuthor Commented:
Nope, haven't tried an XML parser because I don't have the time to implement one.   As the program name, SocketSplitter, suggests,  the purpose of this program is to channel incoming messages from that given port to 2 other ports for other applications to use.
0
objectsCommented:
There are lots of parser implementations available, a SAX parser sounds like it would be suitable for your application.

What do the other apps expect? Could you simply pass the data recieved directly to the other ports without worrying where the end of message was?
0
CEHJCommented:
>>The XML coming in could be any XML message

It seems strange that your message 'packet' is not standardized. Are you getting them from several different sources?

Broadly speaking, there are two approaches you could take here, which we have discussed already:

a. You use the TCP/IP sockets and streams and close them. We have eliminated this presumably as you have no control over implementation of the sending source of these messages.
b. You use a protocol. One of the minimum requirements of this would be to agree on a message format. You could of course extends this protocol to include all sorts of functionality, but you should probably, as in any other xml-based protocol, have a dtd-based message format.

I can't think of any good way to design software to receive messages that doesn't follow one of the above.
0
LunchyCommented:
PAQed, with points refunded (250)

Lunchy
Friendly Neighbourhood Community Support Admin
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
CEHJCommented:
>>If you have not responded to the Experts concerning your question or given an updated status, your points will not be refunded.

>>PAQed, with points refunded (250

??


0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.