sending Objects and Strings over TCP/IP

T

Tomek Gruca

Hello,

I would like to send objects as well as simple strings over a tcp/ip
connection.
I already have much code using InputStreamReader and PrintWriter for
sending strings, now I want to add some functionality with
ObjectInput/OutputStream (serialization).

For sending strings I use:
Socket socket = ........;
InputStreamReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
and then:
String s;
if( in.ready() ) s = in.readLine();
out.println(s);

Now can I send an object over _opened tcp connection_ (same sockets as
above)?
objectIn = new
ObjectOutputStream objectOut = new
ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectIn = new
ObjectInputStream(socket.getOutputStream());
and then:
someObj = (SomeClass) in.readObject();
in.writeObject(someObj);

When I do it this way I get "StreamCorruptedException: invalid stream
header".
Is there something wrong or it's just impossible to have 2 wrappers
over same socket streams?

I could send strings also as objects using only
ObjectInput/OutputStream but the functionality I miss here is
in.ready() method...
 
G

Gordon Beaton

I could send strings also as objects using only
ObjectInput/OutputStream but the functionality I miss here is
in.ready() method...

Honestly, what do you gain from ready()? It isn't apparent from your
example. Why don't you just block in the call to readLine() etc?

Realize that readLine() can block anyway even though ready() returns
true, since there may not be a complete line "ready". Also the use of
ready() makes it difficult to reliably detect EOF on the stream.

/gordon
 
T

Tomek Gruca

Gordon said:
Honestly, what do you gain from ready()? It isn't apparent from your
example. Why don't you just block in the call to readLine() etc?

while(end == true){
if(in.ready())
s = in.readLine();
else
sleep(100);
}

I use to be able to stop the loop with "end = true;".
Is there a better way to do it?
Realize that readLine() can block anyway even though ready() returns
true, since there may not be a complete line "ready". Also the use of
ready() makes it difficult to reliably detect EOF on the stream.

Actually I didn't know that - I thought ready means a ready line...
I could use (objectIn.available() > 0) instead of ready().

I thing i'll move everything to objects, but if someone knows how it is
with double streams over socked.getInputStream() please let me know..

Thanks for your answer, Gordon.
 
G

Gordon Beaton

while(end == true){
if(in.ready())
s = in.readLine();
else
sleep(100);
}

I use to be able to stop the loop with "end = true;".
Is there a better way to do it?

If non-blocking is not important, then just loop around calls to
readLine().

If you really want non-blocking IO then java.nio is a better way to
go. To read lines of text, the proper non-blocking way to do it is to
read character data from the stream and assemble the lines yourself,
since readLine() will block until a complete line is available.
Actually I didn't know that - I thought ready means a ready line...
I could use (objectIn.available() > 0) instead of ready().

There is no practical difference between ready() and available() in
this respect.
I thing i'll move everything to objects, but if someone knows how it
is with double streams over socked.getInputStream() please let me
know..

As you've already discovered, it's not really a good solution...

/gordon
 
P

Patrick May

Tomek Gruca said:
I would like to send objects as well as simple strings over a tcp/ip
connection.

Could you explain why you want to do this? Would RMI or Jini
provide the capabilities you need?

Regards,

Patrick
 
T

Tomek Gruca

Patrick said:
Could you explain why you want to do this? Would RMI or Jini
provide the capabilities you need?
Because I didn't want to change my old code.


I've read that ObjectInputStream.available() returns always 0. So I
can't use "in.available() > 0" as a replacement.

How to cleanly inform a client that we lost connection with server?
Earlier it was:
while(end == true){
if ( /* checking if connection lost */ )
popUp("Connection lost.");
else if(in.ready())
parsePacket( in.readLine() );
else
sleep(100);
}

How to achive it with blocking architecture? Is there something like
timeout with ObjectInputStream. Or do I need to use another thread?
 
E

EJP

Agree with Gordon's comment. Calling ready() or available() is almost
always a complete waste of time. I did see a valid use for these things
the other day but it was the first time in about 20 years of TCP/IP
programming.

Regarding your problem, you'll have to use a single stream rather than
two, which is very problematic. ObjectOutputStream extends
DataOutputStream so you can use writeUTF() for your Strings, and
similarly ObjectInputStream extends DataInputStream so you can use
DataInputStream.readUTF().

Better still, just use readObject() and writeObject() for everything.
 
P

Patrick May

Tomek Gruca said:
Because I didn't want to change my old code.

I was referring to why you want to pass the objects in the first
place. Are you going to instantiate and use them in another JVM?

Regards,

Patrick
 
E

EJP

Tomek said:
I've read that ObjectInputStream.available() returns always 0.

There is no truth in this. Don't believe everything you read. Unless
maybe it's in the Javadoc, which it isn't.
How to cleanly inform a client that we lost connection with server?
Earlier it was:
while(end == true){
if ( /* checking if connection lost */ )
popUp("Connection lost.");

There is no test you can validly use here other than a write, so this
line is pointless.
else if(in.ready())
parsePacket( in.readLine() );
else
sleep(100);
}

And this sleep is a waste of time if the next piece of data arrives in <
100ms.

You can replace all this with something that will work, by setting a
read timeout on the socket and just calling readLine(). If the timeout
happens, assume the connection is lost. Choose your timeout period
accordingly.
 
T

Tomek Gruca

Thanks to you all.

Patrick said:
I was referring to why you want to pass the objects in the first
place. Are you going to instantiate and use them in another JVM?

Yes, I'm writing a game and I'm sending whole game state as one object
- encoding it to strings would be a bit problematic.

Ian said:
How does that differ from this?
while(end) {

There should be "end == false" of course.. retyped it wrong. And I see
the difference between "end == false" and "!end"...
 
L

Lew

Tomek said:
There should be "end == false" of course.. retyped it wrong. And I see
the difference between "end == false" and "!end"...

So you are going to go with "! end", aren't you?

- Lew
 
I

Ian Wilson

Tomek said:
I see the difference between "end == false" and "!end"...

I find "while(!finished) { ..." to be closer to the way I'd express it
in my mother tongue: "while not finished".

If I wanted to avoid people missing the exclamation mark then I'd write
it as "while (unfinished) { ..." or "while (incomplete) { ..."

I find this far far preferable to awkward constructions like
"end == false",
"(end == false) == true"
 

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

No members online now.

Forum statistics

Threads
473,979
Messages
2,570,185
Members
46,728
Latest member
FernMcmull

Latest Threads

Top