使用Java中的套接字自动重新连接到服务器

时间:2014-01-11 20:35:21

标签: java sockets tcp connection-timeout

我的应用程序中有一个组件通过TCP侦听服务器(因此它只接收数据,从不使用输出流)。潜在脱节的唯一原因是技术问题。从逻辑的角度来看,连接应该永远保持开放。

我知道如果我想立即检测连接失败,我必须实施某种ping / pong策略。但在我的情况下,没有必要立即检测掉连接,只要它被检测到(让我们说几分钟或几小时后)。

我的问题:

  1. 如果我不使用某种乒乓/活动检查策略并且连接断开,我会在一段时间后在我的应用程序逻辑中获得IOException(如果花费几个小时就可以)或者是否可能根本没有检测到丢弃的连接?
  2. 以下代码是否符合我的要求?它有点难看(许多try-catch / while(true)甚至睡眠,但我想知道在一定时间后是否可以识别超时连接(例如由于阻塞BufferedReader.readLine方法中的IOException) )。
  3. 除上述问题外,我还能做些什么?

    public class Receiver implements Runnable {
    
    private Socket socket;
    private final String host;
    private final int port;
    private final int connectionRetryAfter = 10* 1000;
    
    public Receiver(String host, int port)  { // assignments... }
    
    @Override
    public void run() {
        tryCreateSocket();
        listenToServer();
    }
    
    private void listenToServer() {
        String receivedLine;
        BufferedReader buf;
        while(true) {
            try {
                buf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                while ((receivedLine = buf.readLine()) != null) {
                    // do something with 'inputLine'
                }
            } catch (IOException e) {
                // logging
            } finally {
                closeSocket();
            }
            // At this point, either an exception occured or the stream equals null (which means it's closed?)
            tryCreateSocket();
        }
    }
    
    private void tryCreateSocket() {
        try {
            socket = new Socket(host, port);
        } catch (IOException e) {
            // logging
            try {
                Thread.sleep(connectionRetryAfter);
            } catch(InterruptedException ex) {
                // logging
                Thread.currentThread().interrupt();
            }
            // retry
            tryCreateSocket();
        }
    }
    
    private void closeSocket() {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                // logging
            }
        }
    }
    

    }

2 个答案:

答案 0 :(得分:2)

如果连接/重新连接尝试失败,

listenToServer()肯定会抛出IOException。考虑服务器关闭时的情况。你真的想永远在这个方法中循环吗?

答案 1 :(得分:0)

您可能需要避免的一个问题是tryCreateSocket()进行递归调用。如果您的客户端长时间断开连接,则可能会耗尽内存。当你重新建立连接时,不会释放内存堆栈。

我建议迭代while循环调用tryCreateSocket()来避免这个问题。