views:

678

answers:

1

I am making a prototype client & server so that I can understand how to handle reconnects. The server ought to create a serversocket and listen forever. A client may connect, send its data, and close its socket but it will not send a "I'm done and closing" type message to the server. For this reason, the server gets a EOFException when it does a readByte() since the remote client has closed. In the error handler for the EOFException, it will close the socket and open a new one.

Here's the problem: The client sometimes gets a SocketWriteError when it does the outputStream.write() call even after it successfully opens the socket/inputstream/outpustream. It may have something to do with the frequency that I'm opening and closing these sockets. One interesting thing is that the client does an arbitrary number of writes/close/reconnects before crapping out. It will sometimes crap out on the first reconnect, other times it will take 50 reconnects before seeing the SocketWriteError.

Here's the error on the client side:

java.net.SocketException: Connection reset by peer: socket write error
       at java.net.SocketOutputStream.socketWrite0(Native Method)
       at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
       at java.net.SocketOutputStream.write(SocketOutputStream.java:115)
       at bytebuffertest.Client.main(Client.java:37)

Here are some snippets of code:

SERVER:

public static void main(String[] args)
{
    Server x = new Server();
    x.initialize();
}

private void initialize()
{
    ServerSocket s;
    InputStream is;
    DataInputStream dis;
    while (true) //ADDED THIS!!!!!!!!!!!!!!!!!!!!!!
    {
        try
        {
            s = new ServerSocket(4448);
            s.setSoTimeout(0);
            s.setReuseAddress(true);
            is = s.accept().getInputStream();
            System.out.println("accepted client");
            dis = new DataInputStream(is);
            try
            {

                byte input = dis.readByte();
                System.out.println("read: " + input);
            } catch (Exception ex)
            {
                System.out.println("Exception");
                dis.close();
                is.close();
                s.close();
            }
        } catch (IOException ex)
        {
            System.out.println("ioexception");
        }
    }
}

CLIENT:

public static void main(String[] args)
{
    Socket s;
    OutputStream os;
    try
    {
        s = new Socket("localhost", 4448);
        s.setKeepAlive(true);
        s.setReuseAddress(true);
        os = s.getOutputStream();
        int counter = 0;
        while (true)
        {
            try
            {
                os.write((byte) counter++);
                os.flush();

                os.close();
                s.close();

                s = new Socket("localhost", 4448);
                s.setKeepAlive(true);
                s.setReuseAddress(true);
                os = s.getOutputStream();
            } catch (Exception e)
            {
                e.printStackTrace();
                System.err.println("ERROR: reconnecting...");
            }
        }
    } catch (Exception ex)
    {
        ex.printStackTrace();
        System.err.println("ERROR: could not connect");
    }
}

Does anyone know how to properly reconnect?

+2  A: 

Don't close the ServerSocket on an error, just .accept() a new connection.

What I normally do is each time ServerSocket.accept() returns a Socket, I spawn off a thread to handle sending and receiving from that Socket. That way you're ready to start accepting a new connection as soon as somebody wants to connect to you.

Paul Tomblin
Yes, I believe this is the answer. Thank you!
jbu