如何使客户端套接字等待服务器套接字

时间:2013-09-04 14:36:11

标签: java sockets

如果客户端套接字在服务器套接字之前打开,Java将生成 ConnectionException 。所以我必须检查服务器是否可用并在执行

之前一直等待

socketChannel.open(hostname, port)

在客户端线程中。我找到了一个相关的API:

InetAddress.getByName(hostname).isReachable()

但是,这仍然无法判断特定端口上的套接字是否已打开。 我认为这个问题应该很常见,但我没有从谷歌和其他地方获得非常有用的信息。

3 个答案:

答案 0 :(得分:11)

boolean scanning=true;
while(scanning)
{
    try
    {
        socketChannel.open(hostname, port);
        scanning=false;
    }
    catch(ConnectionException e)
    {
        System.out.println("Connect failed, waiting and trying again");
        try
        {
            Thread.sleep(2000);//2 seconds
        }
        catch(InterruptedException ie){
            ie.printStackTrace();
        }
    } 
}

这是声音评论的代码

答案 1 :(得分:1)

我会为你的客户提供这种处理程序,我在我的小游戏中使用它。

它也会在几次后放弃。

private static int MAX_CONNECTION = 10;
private int reconnections = 0;

public void connect() {

            try {
                    this.socket = new Socket();
                    InetSocketAddress sa = new InetSocketAddress(this.server, this.port);
                    this.socket.connect(sa,500);
                    this.connected = true;

                    this.in = new InputStreamReader(this.socket.getInputStream());
                    this.out = new OutputStreamWriter(this.socket.getOutputStream());
            } catch (ConnectException e) {
                    System.out.println("Error while connecting. " + e.getMessage());
                    this.tryToReconnect();
            } catch (SocketTimeoutException e) {
                    System.out.println("Connection: " + e.getMessage() + ".");
                    this.tryToReconnect();
            } catch (IOException e) {
                    e.printStackTrace();
            }

    }
private void tryToReconnect() {
            this.disconnect();

            System.out.println("I will try to reconnect in 10 seconds... (" + this.reconnections + "/10)");
            try {
                    Thread.sleep(10000); //milliseconds
            } catch (InterruptedException e) {
            }

            if (this.reconnections < MAX_RECONNECTIONS) {
                    this.reconnections++;
                    this.connect();

            } else {
                    System.out.println("Reconnection failed, exeeded max reconnection tries. Shutting down.");
                    this.disconnect();
                    System.exit(0);
                    return;
            }

    }

以下是代码的解释:

private static final int MAX_CONNECTION = 10;
private int reconnections = 0;

首先我宣布两个vars,一个是固定的,不能在运行时更改,这是我希望客户端在关闭之前完成的最大尝试次数。第二个是当前的重新连接尝试。

public method connect()用于连接套接字。我将跳过异常处理:

} catch (ConnectException e) {
    System.out.println("Error while connecting. " + e.getMessage());
    this.tryToReconnect();
} catch (SocketTimeoutException e) {
    System.out.println("Connection: " + e.getMessage() + ".");
    this.tryToReconnect();
}

当抛出连接异常时,捕手会调用重新连接方法。

重新连接方法在每次尝试之间等待10秒,如果失败则每次都通过connect()调用。

如果建立连接,则connect()不会再次调用tryToReconnect()。 如果无法在100秒内连接10次尝试每10秒一次,则程序退出。

答案 2 :(得分:0)

我来到这个大会上是为了寻找答案,然后我发表了“这种方式”的评论。现在,似乎很公平,社区也愿意分享我自己的答案,并从我自己的工作代码(经过绿色单元测试)中复制并粘贴不变:

private void makeSocketWithRetries(long maxWaitMS) throws IOException {
    Stopwatch retryWatch = new Stopwatch().reset();
    final long retryWaitMS = 500;

    do {
        try {
            socket = new Socket(host, port);
        }
        catch (ConnectException e) {
            logger.info("failed to connect tp [" + host + ":" + port + "]: retrying in " + retryWaitMS + "(ms)");
            try {
                Thread.sleep(retryWaitMS);
            } catch (InterruptedException interruptedException) {
                // swallow this exception
            }
        }
    }
    while ((socket == null) && (retryWatch.mark().deltaMS() <= maxWaitMS));

    if (socket == null) {
        String msg = "failed to connect tp [" + host + ":" + port + "] total wait time exceeded: " + retryWatch.deltaMS() + "(ms)";
        logger.info(msg);
        throw new ConnectException(msg);
    }
}

话虽如此,这里有一些注意事项:

  1. 日志记录有点多,但是它显示了正在发生的事情。跟踪记录 对于重试更有意义,也许对于“时间” 超出”异常。或者只是完全丢弃日志。
  2. retryWait应该是一个类常量(或带有 验证/范围上限/对数警告(如果很大的话等)。至少它是本地最终#8-)__
  3. 我的Stopwatch实用工具类未显示,但它应 很有希望是不言而喻的。
  4. 尽管参数maxWaitMS为否,但不检查参数 等待仍会至少进行一次尝试。

另外,我不计算(也不限制)重试次数。根据我对@Cruncher解决方案的评论,我认为它通常不是有用的功能。