Reputation: 2627
I currently have a simple instant messaging program which is utilizing Java's Socket and ServerSocket classes. It is functioning as intended but when I attempt to close the connection it is not using the 4 way handshake TCP teardown to close the connection. Instead it is closing the connection abruptly with an RST packet.
The way in which I am closing the connection is sending a string from the client to the server which the server will recognize as the command to close the connection. I then use the ServerSocket.close()
method on the server and the Socket.close()
method on the client.
What is the correct way and/or order of events to properly close a TCP connection utilizing these classes?
Client side disconnect code:
//Disconnects from remote server
//Returns true on success, false on failure
public boolean disconnect(){
try{
this.clientOut.println("0x000000");
this.clientRemoteSocket.close();
this.isConnected = false;
return true;
}catch(Exception e){
return false;
}
}
Server side disconnect code:
//Check to see if the client wants to close the connection
//If yes, then close the connection and break out of the while loop
if(incoming.equals("0x000000")){
serverLocalSocket.close();
break;
}
EDIT: The code works perfectly fine. I'm just trying to learn socket programming in Java and know that a proper TCP teardown process is to include a 4 way handshake. A FIN packet to the remote host, then an ACK packet from the remote host back. Then a FIN packet from the remote host, then an ACK packet to the remote host. When monitoring the traffic via Wireshark I am not getting that. Instead I am getting a FIN to the remote server, then a RST/ACK back from the server.
This image depicts a proper TCP 4 way teardown process.
So far everything I've found suggest that all one needs is a call to close() or to just let Java's Try-with-resources statement handle the clean up. I can't see Java implementing functionality which does not comply with the standard TCP specifications though. It is very possible I may be calling certain lines in an incorrect order or something of the sort, I'm just unaware of it.
Upvotes: 3
Views: 13673
Reputation: 311023
If you are resetting your own connection on close, either:
In both cases, an application protocol error.
Upvotes: 3
Reputation: 13596
The great part about TCP is if you close your socket, your partner will automatically know and throw an error on reading.
So all you have to do in the client is:
clientRemoteSocket.close();
And with the server, just add an error case to your normal reading of data:
try {
// Read from the socket:
incoming = socketInputStream.read();
// Handle the data here
} catch (IOException e) {
// Client has disconnected
}
There might be a more specfic exception you can catch, I'm not sure, it's been a while. But that should work. Good luck!
Upvotes: 1