如果客户端套接字在服务器套接字之前打开,Java 将生成ConnectionException。所以我必须检查服务器是否可用并在执行之前一直等待
socketChannel.open(hostname, port)
在客户端线程中。我找到了一个相关的 API:
InetAddress.getByName(hostname).isReachable()
但是,这仍然无法判断特定端口上的套接字是否打开。我认为这个问题应该很常见,但我没有从谷歌和其他地方得到非常有用的信息。
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();
}
}
}
这是 sonics 评论的代码
我将为您的客户提供这种处理程序,我在我的小游戏中使用它。
几次后它也会放弃。
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;
首先我声明了两个变量,一个是固定的,不能在运行时更改,这是我希望客户端在关闭之前进行的最大尝试次数。第二个是当前的重新连接尝试。
公共方法 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 次,则程序退出。
我来到这个车队寻找答案,然后我做了一个“这样怎么样”的评论。现在,分享我自己的答案似乎是公平和具有社区意识的,从我自己的工作(绿色单元测试)代码中复制并粘贴不变:
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);
}
}
这就是“说”,这里有一些注意事项:
retryWait
应该是一个类常量(或者一个带有验证/范围上限/ log.warning 如果非常大/等的参数)至少它是一个本地最终#8-)__Stopwatch
实用程序类没有显示,但它maxWaitMS
等待仍将至少进行一次尝试。另外,我不计算(也不限制)重试次数。根据我对@Cruncher 解决方案的评论,我认为这通常不是一个有用的功能。