This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I am trying to establish server-client streams to communicate information to & from, with buffered streams. The problem is I can communicate from server to client just fine, but I can't get it to work the other way around.
Here is the code for the server:
And here is the code for the client:
If I uncomment out the line "ObjectInputStream in = new ObjectInputStream(socket.getInputStream());" in the server code, it hangs on that line.
Any suggestions? [ July 26, 2008: Message edited by: Joseph Macer ]
The problem is that when you are creating your input stream, you are using an ObjectInputStream. ObjectInputStreams (and ObjectOutpuStreams) are for object serialization. If you read the javadoc for the ObjectInputStream constructor you are using, you will see this (multiple emphasis added):
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified.This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
So the constructor is blocking until it sees the proper serialization stream header, which never comes. So your application hangs.
Were you planning to send serialized objects? If not, you need to use a different type of InputStream. Yyou can use the received InputStream itself, or wrap it if you needed additional functionality. (Also change your ObjectOutputStream in the server code.) If you are planning to do Object serialization, you need to have your client code send the serialized object so the ObjectInputStream constructor can read and verify the serialization stream header. And you would likely want to have the ObjectInputStream created and executing in a separate thread in the Server.
Joined: Apr 20, 2008
Yes, I need to have buffered object serialization going both ways. I now see why the server is blocking, but how do I get the client to flush the header so the server can continue?
Right now your client is not sending anything, let alone an object. So there is nothing to flush.
You will also need to resolve some synchronization problems. As it is right now, you have a lock. The server is not sending the "test string" object because it is waiting for the client to send a serialized object (since the ObjectInputStream is blocking). Meanwhile, the client is waiting for the server to send something (i.e. the "test string"). So each side is waiting for the other to send something.
To resolve this, in the server code, you need to move the creation of the ObjectInputStream to after you send the "test string". This will allow the client to receive the testString. If you run the code like this, you will see the client receive and print out the test String. The server will start to create the ObjectInputStream. The ObjectInputStream constructor blocks (i.e. waits) for the client to send an object. But then at this point, the client code is finished, so it exits. Upon doing so, the socket connection and its underlying streams close and the server will throw a java.net.SocketException.
So we now need to have the client send an object. So in the client, after it receives and prints out the object it receives form the server, have it send an object. Below is your code modified as an example:
This will: 1) have the server send a String object to the client; 2) the client receive and print it; 3) the client sends a Date object to the server; 4) the server receives and prints out the received object; 5) the client disconnects and the server waits for another connection.
If that's OK, then great. But if you need more flexibility in terms of which side sends what when, you'll need to put some more logic around things. For example have one or the other side send a "command" to tell the other, "I want to send you an object. Are you Ready?" The other side then needs to acknowledge and get ready to receive the object. So basically, you need to determine a protocol for your client and server to communicate. If you want to get past anything but a very stringent a-b-c-d like protocol where things are always done in the exact same order, you will likely want to (or need to ) multi-thread things. It's a fun exercise to make such things.
I hope that helps.
Joined: Apr 20, 2008
Yes it does. I created this code to understand how to use buffers; I already have a nice multi-threaded server/client setup, it just doesn't use buffers, which means it gets terrible performance over the internet. When I tried just slapping in buffered input/output streams in my stream declarations, stuff got hung up, and I can see why.
I'll try this stuff out & post again later. [ July 27, 2008: Message edited by: Joseph Macer ]
Joined: Apr 20, 2008
Excellent. My server now buffers outgoing data properly. Thanks for your help.
One more question though: is it important to make the input streams buffered too? Since the data should already arrive in buffered packets, it doesn't seem like it'd need a buffer...
Originally posted by Joseph Macer: One more question though: is it important to make the input streams buffered too? Since the data should already arrive in buffered packets, it doesn't seem like it'd need a buffer...
I'm no I/O guru, but I think you'd be okay not buffering them since the Socket InputStream is apparently buffered. When I wrote the above example, I didn't dig into SocketInputStreams to determine if they were buffered or not, and wrapped in a BufferedInputStream more out of habit than anything else.