I'm working on a network app written in Java, using ObjectOutputStream and ObjectInputStream on top of Sockets to exchange messages. My code looks like this:
Sender:
ObjectOutputStream out;
ObjectInputStream in;
try{
Socket socket=new Socket(address, port);
socket.setSoLinger(true, socketLingerTime);
out=new ObjectOutputStream(socket.getOutputStream());
out.writeObject(message);
out.flush();
out.close();
}catch (variousExceptions)...
Receiver:
Object incoming;
try{
incoming=myObjectInputStream.readObject();
}catch (SocketException socketError)
{
if (socketError.getMessage().equals("Connection reset"))
{
//this is the exception I get
}
}
Sometimes the message goes through ok, but other times I get the marked exception instead of an object. Isn't flush supposed to force the message through to the other side? Am I somehow using the function incorrectly? Or is this some sort of bug in the underlying Java/OS network code?
Thanks!
UPDATE:
I've done some more snooping on this, and it seems to only happen when the system's resources are being taxed by something. I've not been able to replicate it outside the VirtualBox, but that could just be because the VirtualBox doesn't have many resources to begin with. I'll keep this question updated as I look into it further.
Connection resets can be caused by writing to a connection that is already closed at the other end. Detection can occur at the next I/O or a subsequent one, e.g. a read. In other words it can be caused by a bug in your application protocol. SO_LINGER won't help, don't mess with this.
It sounds like a firewall in one of the routers in the path from client to server is sending an RST for some reason. I don't believe there's anything wrong with your code. I tried to replicate the problem, but couldn't.
You should be able to send one object per connection.
To ensure resources are cleaned up in an orderly manner it is best to close the socket as well as the output stream.
close() will call flush so it should be redundant.
What happens if you don't set the SO Linger?
What is the actual exception you are getting?
It turns out the issue was caused by Nagle's Algorithm; the output buffer is within the OS, so it wasn't affected by flush. The solution is to turn Nagle's Algorithm off using Socket.setTcpNoDelay(true), and buffer messages at the user level using BufferedOutputStream.
For my case, it's a silly problem but wasting me 4 hours. Just have to use outStream.writeln(""); or outStream.write(mess + "\n"); Since reader.readLine() reads until it finds '\n' character. So write() alone won't work.