In a client-server application, I send a string to the server in a separate thread:
dataOutputStream.writeUTF(_dos);
dataOutputStream.flush();
But I get in another thread java.net.SocketException: Connection reset in the line:
mes = dataInputStream.readUTF();
At the same time, the server does not receive anything (I checked this in wireshark) and continues to listen to the socket.
The question is: is it possible, if the client socket is damaged, but the server socket is working, to restore the operation of the client socket and thus restore the client-server connection, without restarting both?
The connection is gone. On the client side, you will need to connect again.
Generally speaking, TCP implementations do not allow you to issue a connect on a socket that has become disconnected. You can try, but it's safest to make a new socket object. Even if it works for you, the result may be non-portable.
The server of course also has a socket on a defunct connection, so it needs to close its end. A new socket will be created on 'accepting' the new connection from the client.
Related
I am currently working on a simple multiplayer game where serveral clients need to connect to a server.
My server consits of a single serverSocket. This serverSocket accepts incoming connections and hands them over to connection object that starts a separate thread.
ServerSocket seso = new ServerSocket(12345);
while(true){
Socket toClient = seso.accept();
new Connection(toClient); //creates a thread that opens streams etc
}
Clients open a new Socket and connect to this server.
Socket toServer = new Socket();
toServer.setReuseAddress(true);
toServer.bind(new InetSocketAddress(65432)); //always using the same port
toServer.connect(new InetSocketAddress(serverIP,12345));
Now if i close the connection to the server using toServer.close(); and try to connect again to the server, i get an "address already in use: connect" exception.
Using TCPView i can see that the state of the client procress changes to TIME_WAIT. But shouldn't i be able to use this port again because of setReuseAddress(true)? Am i using it wrong or is it an server problem?
I do always call .close() on toClient and toServer. Nevertheless i always have to wait until the socket is completely closed (after TIME_WAIT) before this client can connect again to the server.
When i close the entire application, the socket is immediately closed (not in state TIME_WAIT) and this client can connect to my server. (And ofc there is a connection reset exception in my server)
How can I do that without always closing the application ?
Thanks for your help.
To expand on my comment, a client / server protocol requires the server to listen on a port known to or discoverable by the client -- that can be considered the definition of "server" -- but it does not ordinarily require clients to connect from a specific port. If you do not bind the client socket to a particular port, then the underlying system will choose an available (source) port automatically and transparently.
If the server depends for some reason on clients connecting from a particular port, then you should re-evaluate that aspect of your design. If it does not, then you are making your own trouble by having clients connect that way. This should be all you need to do:
Socket toServer = new Socket();
toServer.connect(new InetSocketAddress(serverIP, 12345));
According to tcp protocol when ever tcp connection termination is going on, tcp socket of initiator go to following states FIN-WAIT-1, FIN-WAIT-2,TIME-WAIT before connection is completly closed and the tcp socket of other end go to following states CLOSE-WAIT, LAST-ACK, CLOSED before connection is completly closed.
In our application server is initiating connection termination which leading to server side sockets are waiting in FIN_WAIT2 state infinitely, due to this connections made by clients are dropped by server because of unavailability of ports.
Is connection termination initiated by clients is favourable or not?
Initiating termination from the client can be favorable because it prevents the server from going to TIME_WAIT. Your problem is different.
A socket in FIN_WAIT2 is "half open": the client side can still send data and you can read it, but you can't send anything back. The socket will stay in this state until the client closes its socket, or the server resets the connection.
So it sounds like your clients are simply not closing their sides of the connections.
My TCP server is implemented using Netty. My client using vanilla java.net.Socket to connect to this server. I'm using the same socket to send multiple requests to the server. Once done with all the requests the client calls socket.close().
I'm not closing the channel anywhere in my server code. Also, I've set TCP KEEP_ALIVE on my server. Will closing the socket on the client end automatically close the channel on the server or do I've to do something else explicitly and what is the best practice ?
Usually, if an application closes a socket, its remote peer also notices that the closure. Therefore, you don't need to call close() on both side. However, sometimes, due to network problems, you might not get notified when the remote peer closes the connection. To work around this problem, it's a good idea to send some message periodically, and then you will detect the unexpected closure sooner.
Please note SO_KEEP_ALIVE will not help much here because for most operating systems because the default keep alive time is very long.
In Java, if I connect to a client to a server via a socket and the client has an exception which causes it to crash, is there any way the server can detect that the socket connection is lost.
I assume one method would be have some sort of heartbeat polling the client, but is there a simpler/easier way?
There are a few ways, depending on what you consider to be a "crash".
If the client process dies, the client OS will close the socket. The server can detect this by performing a read(), which will either return -1 (EOF) or raise a SocketException ("connection reset").
If the client gets into an infinite loop, the connection will remain open; the only way to detect this is by incorporating some kind of "heartbeat" into your protocol.
If the client host is rebooted or the network connection breaks, the server may not notice unless either:
the protocol has a "heartbeat" mechanism as above, with some kind of timeout, or
TCP keepalive is enabled on the socket by calling socket.setKeepAlive(true) - this instructs the OS to periodically* send a packet to check that the remote end of the connection is alive, closing the connection if not
*both Windows and Linux default to 2 hours; you can change this system-wide but not per-socket (under Java, anyway)
TCP sockets do this anyway, and Java exposes it to the developer. See setKeepAlive() / getKeepAlive() in the Socket class. If a TCP message isn't sent from the client to the server for a certain period of time, the socket will close, and the server can remove the session information because it still has its endpoint.
I learned an example of usage of sockets. In this example a client sends a request to a server to open a socket and then the server (listening to a specific port) opens a socket and everything is fine, socket is "opened" from both sides (client and server).
But it is still not clear to me how flexible is this stuff. For example, is it possible for the client to close an opened (from both ends) socket and to reopen it again (under condition that the server keeps the socket opened).
Is it possible for the server to "know" that a socket was closed on the client side? Is it possible for the client to know that a socket was closed on the server side?
ADDED:
One more important thing to me. What happens if a application (no mater server or client) crashes, abnormally terminated, killed? Will it close all sockets opened on the side of the application?
ADDED 2:
What if an application on one side of the socket is switched off (killed, closed, terminated) and then it is switched on again (on the same IP address and the same port). Should we create a new socket between the two applications or we can use the old socket (created before the crash).
A socket can be used for a lot of things for which the answers to these questions would change, but I'll assume you're talking about TCP.
For example, is it possible for the client to close an opened (from both ends) socket and to reopen it again (under condition that the server keeps the socket opened).
No, because TCP will perform a goodbye and you can't pick up the connection from there again. You'd have to do the three-way handshake again, and that starts a brand new connection.
Is it possible for the server to "know" that a socket was closed on the client side? Is it possible for the client to know that a socket was closed on the server side?
Yes. TCP can send out a goodbye packet or one side can time out and it's entirely possible to detect these scenarios in both cases.
Is it possible for the server to
"know" that a socket was closed on the
client side?
When server tries to send some data to that client a correspondent exception will be thrown.
One more important thing to me. What
happens if a application (no mater
server or client) crashes, abnormally
terminated, killed? Will it close all
sockets opened on the side of the
application?
Exceptions are created for handling these abnormal cases. If there is a black out and a client (or server) is turned off then other side will get an exception as soon as it try to interact with turned off side.
UPD:
What if an application on one side of
the socket is switched off (killed,
closed, terminated) and then it is
switched on again (on the same IP
address and the same port). Should we
create a new socket between the two
applications or we can use the old
socket (created before the crash).
Create new socket.
Q1->Is it possible for the server to "know" that a socket was closed on the client side? Is it possible for the client to know that a socket was closed on the server side?
A1 -> The sever will know, if client closes socket and vice versa. Actually FIN will be sent from the end, which is initiating to close connection.
Q2-> What if an application on one side of the socket is switched off (killed, closed, terminated) and then it is switched on again (on the same IP address and the same port). Should we create a new socket between the two applications or we can use the old socket (created before the crash).
A2->If socket is created, fd number is bind with ip-addr & port, so socket on server side has server-ip & some port and socket on client side has client-ip & some port. if crash happened at client the all fd are freed and it can not be reused.if we use the same fd, system will treat it as normal file fd.