客户端重新连接java套接字

时间:2012-03-20 20:39:16

标签: java sockets

好吧我需要编写一个能够检测客户端和服务器之间连接的客户端...一旦服务器关闭并恢复我的客户端需要能够将其连接回服务器..但是我我真的不知道怎么做......如果可能的话,有什么帮助吗?

 public TEST(String serverIP, int serverPort){
    Log("Connection to the Server....");
    try{
        socket = new Socket(serverIP, serverPort);
        Log("Connected to the server : "+socket);
        start();
    } catch(UnknownHostException uhe){
        System.out.println("Unknown Host: "+ uhe.getMessage());
    } catch (IOException ioe){
        System.out.println("IO Exception: "+ioe.getMessage());
    }

    String readline = "";

    streamOutput.println("TRY test");

    while(true){
        try{
            readline = streamInput.readLine();
            System.out.println(readline);
        } catch (IOException ioe){
            System.out.println("Error in sending: "+ioe.getMessage());
            return;
        }
    }
}

上面是我的客户端代码,用于在编译后连接到服务器......

4 个答案:

答案 0 :(得分:5)

知道连接关闭的唯一方法是尝试通过线路发送数据。连接不会自动测试打开/关闭状态。如果要检查已关闭的连接并重新连接,则必须将心跳信号从一个发送到另一个。通常,它只是一个特殊的字节或微小的消息告诉对方“我还在这里”

但是,根据您的应用程序,您可能不需要它。应用程序的两端是否都会启动消息?或者它是一个RMI风格的应用程序?服务器只是在监听请求?

也许是这样的?

    class Client {
        private Socket socket;
        private boolean tryToReconnect = true;
        private final Thread heartbeatThread;
        private long heartbeatDelayMillis = 5000;

        public Client(final String server, final int port) {
            connect(server, port);
            heartbeatThread = new Thread() {
                public void run() {
                    while (tryToReconnect) {
                        //send a test signal
                        try {
                            socket.getOutputStream().write(666);
                            sleep(heartbeatDelayMillis);
                        } catch (InterruptedException e) {
                            // You may or may not want to stop the thread here
                            // tryToReconnect = false;
                        } catch (IOException e) {
                            logger.warn("Server is offline");
                            connect(server, port);
                        }
                    }
                };
            };
            heartbeatThread.start();
        }

        private void connect(String server, int port){
            try {
                socket = new Socket(server, port);
            } catch (UnknownHostException e) {
                logger.error(e, e);
            } catch (IOException e) {
                logger.error(e, e);
            }
        }

        public void shutdown() {
            tryToReconnect = false;
        }
    }

答案 1 :(得分:1)

这是一个非常常见的问题(需要知道管道何时损坏),其中一个答案是正确的,说明客户端需要“检查”套接字(定期)看它是否关闭。 服务器不会通知客户端套接字已关闭,实际上,不能,因为它已关闭。在客户端服务器之间的防火墙,代理等可能在连接完成后的任何时刻在一个或两个方向上杀死或以其他方式阻止套接字通信。

首先,如果您已经完成了很多套接字编程(在“C”或Java等中)......您将看到“尝试写入损坏的管道”类型错误/异常。当客户端尝试在已关闭的套接字(之后检测到已关闭)上写入(发送)数据时,这是一个I / O类错误。

所以答案在于管理套接字创建层之上的套接字。

也就是说,客户端上的一个线程需要通过发送数据来监视套接字(定期向服务器发送一种'ping'以检查管道是否损坏)和如果发生I / O错误,则销毁(清理)并重新创建套接字(冲洗并重复)。

请注意,如果客户端可以确保服务器针对给定的“ping”做出预期且一致的(及时)响应,则更复杂的双向逻辑位会更好。这将具体确认双向交通正在流动。否则防火墙可能会在一个方向关闭流量,而客户认为它仍在与服务器“对话”(可能正在接收数据但无法传输回客户端 - 可能导致它在不活动超时时终止连接。)

答案 2 :(得分:0)

当您的客户端捕获SocketException时,它应该进入 tryToReconnect 状态。现在它以某个间隔探测服务器(例如,可能更长1秒,具体取决于服务器)。确保你实现了一些逻辑,以便在不再需要它时停止它。

答案 3 :(得分:0)

似乎您不需要自己实现听节拍。它们已在大多数 TCP 实现中实现。

如果您的连接是 TCP,则您要查找的内容位于较低层。看看 TCP KeepAlive。


这些链接可能会有所帮助:

  1. How To Test TCP KeepAlive?
  2. TCP keepalive overview