【问题标题】:client reconnect java socket客户端重新连接java套接字
【发布时间】:2012-03-20 20:39:15
【问题描述】:

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

 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;
        }
    }
}

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

【问题讨论】:

  • 那么服务器关闭连接时需要重新连接吗?
  • 是的,我需要一些可以检测服务器是否处于活动状态的东西,如果不是,那么将尝试重新连接......

标签: java sockets


【解决方案1】:

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

但是,根据您的应用程序,您可能不需要它。您的应用程序的双方都开始消息吗?或者它是一个 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;
        }
    }

【讨论】:

  • 不是 RMI 应用程序。只是使用套接字的普通服务器和客户端应用程序,但我的问题是我需要为这个项目设计一些调​​用恢复能力,我需要通过关闭服务器应用程序来演示目的是通过客户端连接...一旦我再次启动服务器,客户端可以自动连接到服务器并开始将数据传输到服务器
  • 是的,那么您肯定需要客户端上的某些东西,它偶尔会向服务器发送一个微小的请求,询问它是否还活着。如果该请求超时或抛出错误,您就知道它已关闭。
  • 如果服务器不活跃,那么如何让客户端在服务器活跃后自动重新连接到服务器?
  • TCP 肯定有一个“封闭”的概念。这就是 FIN 的用途。它没有的是会立即显示连接断开的拨号音。
  • 已更新和更正。我很感激更正。现在你提到它似乎很明显。这就是为什么您在发送数据时可以立即获得关闭连接异常的原因。
【解决方案2】:

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      看来您不需要自己实现“听觉节拍”。它们已经在大多数 TCP 实现中实现。

      如果您的连接是 TCP,那么您正在寻找的是较低层。看看 TCP KeepAlive。


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

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

      【讨论】:

        猜你喜欢
        • 2013-04-21
        • 2017-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-05
        • 2023-03-11
        • 2015-02-08
        • 2019-09-30
        相关资源
        最近更新 更多