Closing a Java Socket safely without server side exceptions - java

What is the Safest way to close a socket connection from client side. Shutdown inputs first or close() the connection straight away?

If your protocol (top of TCP) does not contain any message/handshake for closing a session, then you must do it by closing TCP connection.
There are two ways to close a TCP connection:
graceful: uses TCP SYN, all undelivered data is transferred (tried). read() of InputStream returns -1;
ungraceful: uses TCP RST, all undelivered data is discarded. read() of InputStream throws an exception.
Both can be done in java with close() function of Socket.
Graceful is the default. Ungraceful, if setsolinger(true,0); is done before the close().

Closing the socket already shuts down both input and output. You don't need to do either of those explicitly.

Related

Java Socket:why is there is no "write timeout" for the socket

There is the connecting timeout value passed to connect method, and there is the reading timeout set using setSoTimeout method. I was wondering why there is no method to set the "writing timeout"? I think there is the writing timeout concept in the TCP Protocol.
It wouldn't be much use.
In general TCP sending is asynchronous to the application. All that send() does is put the data into the socket send buffer. It then returns, while the send buffer is emptied to the network asynchronously. So there is nothing to timeout. And the absence of a timeout does not denote that the data has been sent to the peer.
send() blocks while the send buffer is full, and it would be possible to implement a timeout on that, and indeed you can do that yourself in non-blocking mode with select(), but the problem is that what timed out could be either the current send or a prior one. So delivering a timeout would be rather confusing. Instead what is delivered when all the TCP send timers time out internally is a connection reset.
I think there is the writing timeout concept in the TCP Protocol.
There is indeed, but that's at the level where TCP is asynchronously emptying the socket send buffer. It isn't under application control.
you can first try to connect...if connect fails catch exception
InetSocketAddress sockAdr = new InetSocketAddress(serveradres, 2222);
Socket newsok = new Socket();
int timeout = 2000;
newsok.connect(sockAdr, timeout);

Clarifications while reading/writing Java socket streams

I have few questions in java socket programming.
while reading the inputstream in client socket, if it throws IO exception; then do we need to reconnect the server socket/ reintialize the client socket again?
if we close the output stream, will it closes the client socket?
in client socket, if the message read from the inputstream is different as what we expected; do we have any standard to handle this?
while reading the inputstream in client socket, if it throws IO exception; then do we need to reconnect the server socket/ reintialize the client socket again?
Yes, unless it was a SocketTimeoutException on a read operation.
if we close the output stream, will it closes the client socket?
Yes.
in client socket, if the message read from the inputstream is different as what we expected; do we have any standard to handle this?
No. If the message is completely unrecognizable, you wil probably want to sever the connection. If it's a recognized message but out of sequence, it may be either a programming error or a condition you didn't think of during design. Solution: think about it now.

Java TCP re-tranmission timeout

public static void main(String args[]){
byte[] message = ...
Socket socket = ...
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
dOut.write(message); //#1
dOut.close();
socket.close();
}
Let's assume that the line #1 will put the data into buffer waiting to flush to remote machine. After that the stream and socket are closed.
We assume that, in the sending process, there is some unknown problem happens in network, and our operating system will resend the packet that was in the buffer until the TCP re-tranmission timeout.
I am wondering that how I can catch this exception in Java program? Because the code above already send out data to buffer and probably closed the stream and socket (and probably exit the Java main body), left all the other job (TCP-related, re-tranmission) to operating system.
My question is, will the TCP re-tranmission (we assume packet lost) continue even Java program exit? What is the best method to catch the re-tranmission timeout error?
TCP will continue to try to cleanly shutdown the connection even after the program exits. It is generally recommended that the application perform the shutdown itself. Basically, you perform the following sequence of steps:
Shutdown the TCP connection in the send direction triggering the normal close sequence. If the protocol prohibits the other side from sending any data, you can shutdown the connection in the receive direction as well, however, if you do this and the other side sends any data, it may cause the other side to detect an abnormal shutdown as the data it sent will be lost.
Continue to read from the connection until you detect a clean or abnormal shutdown from the other end. If all goes well, you will detect a clean shutdown as soon as you finish receiving any data the other side has sent.
Close the handle or delete the object/reference to the connection. The actual TCP connection is already shut down.

Chat server writing to closed sockets

Essentially I have a server class and a client class, the client creates a socket and sends whatever you type into the server, which gets written to the output streams of a vector of sockets from all the existing clients. It works well except when you close a chat client, after which the next message sent gives the following exception:
java.net.SocketException: Software caused connection abort: socket write error
I think what's happening is that the socket closed by the client is either not closing the socket in the server's vector of sockets, or that even when it's closed, it remains in the vector and then tries to write to a closed socket. Does this sound like what might be happening? I don't understand exactly what the socket.close() method does regarding the socket it's connected to.
You close the socket on the client side, but on the server side it is not closed and this is why you get this exception.
In a graceful close you should send a CLOSE message from your client which will close the socket on the server side.
If a socket on the client was closed then you must handle your exception on the server side e.g. by removing it from your vector of sockets.
If the client closes his socket you will read EOS at the server (read() returns -1, readLine() returns null,readXXX() throws EOFException for any other X), or get an IOException: connection reset by peer when writing, probably not on the first write. If either of these things happens you must close the socket in the server and forget about that client in all ways.
I don't think it's like both sides of connection are holding together by hands, and if you split them they always will feel it. Check if socket is closed before sending and catch exceptions to solve this problem.

Configure a Java Socket to fail-fast on disconnect?

I have a listening port on my server that I'm connecting to using a Java class and the Socket interface, i.e.
Socket mySocket = new Socket(host,port);
I then grab an OutputStream, decorate with a PrintWriter in autoflush mode and I'm laughing - except if the listening port closes. Then I get
tcp4 0 0 *.9999 *.* LISTEN
tcp 0 0 127.0.0.1.45737 127.0.0.1.9999 CLOSE_WAIT
and I can't seem to detect the problem in the program - I've tried using the isConnected() method on the socket but it doesn't seem to know that the connection is closed.
I want to be aware of the problem the next time I try and write to the Socket so that I can try and reconnect and report the issue.
Any advice please?
Thanks all
Set a short timeout?
Does isOutputShutdown() not get you what you want?
You could always build a SocketWatcher class that spins up in its own Thread and repeatedly tries to write empty strings to the Socket until that raises a SocketClosedException.
The only reliable way to detect a broken connection in TCP is to write to it, which will eventually cause a 'connection reset' IOException. However due to buffering it won't happen on the first write after the disconnection,p but on a subsequent write. You can't do anything about this.
Set a different thread to reading from the socket. It will block until the socket is closed, and then an exception will be thrown. Catch that exception to detect the close immediately.

Categories