ObjectInputStream blocking in readObject() - java

I'm writing a client/server application in which server sends serializable objects to client via ObjectOutputStream (i'll call it oos from now on) and client gets 'em with ObjectInputStream ("ois" from now on).
Now, since the server is executed first, I initialize the oos first. As it should be. Here's how I initialize it:
OutputStream outStream=incoming.getOutputStream();
DataOutputStream outToClient=new DataOutputStream(outStream);
outToClient.flush();
ObjectOutputStream oos = new ObjectOutputStream(outStream);
oos.flush();
Then I start the client and I initialize the ois with these line:
inStream = clientSocket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(inStream);
From now on, the server side will send many objects on the same stream this way:
oos.writeUnshared(wishes);
in a while loop.
The problem is: when I execute this goddamn code on my pc alone, it's all good. No problems at all. When I try on two different machines, deadlock appears. The client side remains hanging on this line forever:
tempWishes = (ArrayList<String>) ois.readObject();
Feel free to ask more details. I didn't share the whole client and server code because it's like 500 lines of code.

This looks suspicious:
DataOutputStream outToClient=new DataOutputStream(outStream);
ObjectOutputStream oos = new ObjectOutputStream(outStream);
Both outToClient and oos are writing to the same underlying stream. This is likely to cause weirdness.
#EJP's suggestion that you remove the DataOutputStream is a good one because the DataOutputStream class isn't what you're after (since you're writing objects), and you almost certainly want a single chain of OutputStreams.

Have you tried using ois.readUnshared() instead of ois.readObject(). Even though it may no be the whole issue, it may be some other, it's good practice to couple write and reads.
Let me know if this fixed it.

Related

Java socket writeByte and newline

I got a question for something I can't seem to understand.
If I use the snippet:
DataOutputStream dataoutput = new DataOutputStream(Socket.getOutputStream());
dataoutput.writeBytes(diagnostics);
dataoutput.flush();
The output:diagnostics that is sent from server to client hangs, where even using .flush() will not help. Only closing the socket will release the data packet.
However, if I add a newline character:
dataoutput.writeBytes(diagnostics+"\n");
it works perfectly. And if you duplicate the code,
dataoutput.writeBytes(diagnostics);
dataoutput.writeBytes(diagnostics);
You get the same output as the one with the /newline without duplicate data. Why?
EDIT: Client-side.
incoming = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
response = incoming.readLine();
Like the good lads puts in the comment you should use a flush to force send the payload to destination of the stream. But if that isn't working i suggest to try the following :
DataOutputStream dataoutput = new DataOutputStream(System.out);
dataoutput.writeBytes(diagnostics);
dataoutput.flush();
So now the destination will be the "local" console. and no remote connection is between the source and the destination of the stream, perhaps you can try for yourself if anything is working properly "locally" (and focus in the DataOutputStream behaviour) and then start to tackle the remote streaming process.
Is it not to much, but hope it helps a little!
Greetings!!

Must server & client have reverse sequence of claiming ObjectOutputStream & ObjectInputStream?

In my experiment,
if Server has this:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
then client side has to do this, in the opposite order:
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Otherwise server and client will deadlock.
What's the reason for this? and is there a formal API spec for it?
Yes. I see how this might happen. The javadoc for the ObjectInputStream constructor says this:
"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 if both the client and the server construct their ObjectInputStream before their ObjectOutputStream, then both will block waiting for the other end to send the serialization stream header.
Note that this is happening at the object stream level, not the socket or bytestream levels. If you are doing simple byte or character or "data" I/O over a socket, you don't need to worry about the order in which the streams are constructed.
Also not, that this is not a problem if you have separate threads on (both) the client and server sides to do the reading and writing. All things being equal, that is probably a better architecture because it allows the client/server communication over the socket to be "full duplex".

Java sockets: Program stops at socket.getInputStream() w/o error?

InetAddress host = InetAddress.getLocalHost();
Socket link = new Socket(host, Integer.parseInt(args[0]));
System.out.println("before input stream");
ObjectInputStream in = new ObjectInputStream(link.getInputStream());
System.out.println("before output stream");
ObjectInputStream out = new ObjectOutputStream(link.getOutputStream());
"before input stream" is the last lifesign on cmd-line. There is no Exception thrown. Why is this happening? I don't understand...
args[0] is 5000.
//edit: flush doesn't help.
This is because the ObjectInputStream(InputStream in)-constructor is a blocking-call if the inputStream is empty.
Quote:
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.
Possibly,
link.getInputStream();
could be returning null, though that should return an error by looking at the class files.
Another thing I noticed was, you declare:
ObjectInputStream out = new ObjectOutputStream(link.getOutputStream());
From this, you are stating a ObjectInputStream as a ObjectOutputStream without a cast (Would not be appropriate here anyways)
you should try:
ObjectOutputStream out = new ObjectOutputStream(link.getOutputStream());
This should work, as the script may queue the System.out, but notice the error before it can be initialized.
Tell me if this works :D

writing an object to socket

I have got a problem in here...!
I want to write a program in which I have to pass some data and packet_no of that data...
So, I am creating an class Packet. I want to send the an Packet object through the OutputStream of the Socket.
How do I achieve this?
Thanks
The thing, that you need, is called an ObjectOutputStream. it is created from the regular OutputStream. At the reciever side you will need the appropriate ObjectInputStream. Your object and all of it's fields must implement Serializable interface.
Example code:
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(p);

Writing to Socket outputStream w/o closing it

I'd like to write some messages to the server.
Each time, for the tramsmitting only, I'm closing the outputStream and reopen it when I have to send the next message.
os.write(msgBytes);
os.write("\r\n".getBytes());
os.flush();
os.close();
How Can I keep this Socket's OutputStream, os, open and still be able to send the message?
Thanks.
I am missing something here. If you don't call close, it will not close. For example,
os.write(msgBytes);
os.write("\r\n".getBytes());
os.flush();
// Do something
os.write("more message");
os.flush();
// When you are finally done
os.close();
In most protocols, the server accepts som kind of EOF symbol. Send such a symbol instead of closing the stream.
For example, IRC servers interpret "\r\n" as the end of a message. This would be 2 messages on one open OutputStream:
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.print("JOIN #channel1\r\n");
printStream.flush( );
printStream.print("JOIN #channel2\r\n");
printStream.flush( );
Also, you should wrap your outputStream with DataOutputStream. This wrapper creates more portable output. Plain OutputStream can cause trouble with certain primitive datatypes if server and client have different computer architectures.
Wrap the Socket's OutputStream in a PrintWriter and call the PrintWriter's println method.
PrintWriter pw = new PrintWriter(socket.getOutputStream());
....
pw.println(message); // call repeatedly to send messages.
....
pw.close(); // when finished writing to server and want to close conn.
I have found the problem and it lays on the client's side.
On the client, I have used -
count = inputStream.read(buffer)) > -1
That means, the client waits till server's outputStream closed, and then processing the incoming data.

Categories

Resources