I'm connecting to a server using sockets. My application acts like a client, sending requests, and also like a server, listenning for notifications. I was using a client socket for the first task (send a message when required) and a server socket for the second (permanently listen for incoming messages). This needs to be some kind of persistent connection.
It happens now I'm required to send and receive using the same port. The only way I found to do this is to have a single socket (client) bound to a certain port. It connects to the server and one thread keeps listenning for incoming messages (by reading the input stream) while another process is launched whenever I need to send a message (by writing to the socket's output stream). The socket is created only once (when the application starts) and its output/input streams reused whenever needed.
This works well for a while. However, when I try to send a message after some idle time (lets say 20 minutes) strange things happen. The first attempt to send a message returns success (although nothing is actually received by the server). The second attempt returns java.net.SocketException: Software caused connection abort: socket write error. I don't understand this behaviour. Can there be a timeout? I only write to the socket after testing if it's connected.. So why is this failing? Also, any other ideas on how to send and receive using the same port? A different and better approach maybe..
Intervening firewalls can time out your connection. You're on the right track but when you get this exception, or indeed any exception, during I/O on a socket there is no alternative but to close it and in your case re-establish the connection with a new socket.
Well I guess it can be a firewall issue. Although sock.isConnected returns true, something must be happening on the TCP level. I must figure that out because I need to have a persistent connection. Using Ethereal I found that my client is writing the first byte only, after what the server replies with TCP RST (reset)... I don't understand, isn't TCP supposed to keep the connection alive by itself (hmm maybe firewall working here?.. don't know..)? Will I have to keep sending pings to the server or something?
Socket.isConnected just tells you whether you have personally called Socket.connect() or new Socket(host, port,...). It doesn't tell you anything about the state of the connection.
You should certainly issue periodic application 'pings' at suitable intervals, and many application protocols do this. For example, Java RMI reuses connections that are less than 15 seconds old but only if they pass a ping test.
In general however you can't insist on a persistent connection over TCP/IP, especially if you have this kind of hardware in the circuit. What you can do is recognize when the connection has been lost and form a new one. The network is going to fail somewhere some time and your program has to be robust against that.