如果客户端套接字在服务器套接字之前打开,Java将生成 ConnectionException 。所以我必须检查服务器是否可用并在执行
之前一直等待 socketChannel.open(hostname, port)
在客户端线程中。我找到了一个相关的API:
InetAddress.getByName(hostname).isReachable()
但是,这仍然无法判断特定端口上的套接字是否已打开。 我认为这个问题应该很常见,但我没有从谷歌和其他地方获得非常有用的信息。
答案 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);
}
}
话虽如此,这里有一些注意事项:
retryWait
应该是一个类常量(或带有
验证/范围上限/对数警告(如果很大的话等)。至少它是本地最终#8-)__ Stopwatch
实用工具类未显示,但它应maxWaitMS
为否,但不检查参数
等待仍会至少进行一次尝试。另外,我不计算(也不限制)重试次数。根据我对@Cruncher解决方案的评论,我认为它通常不是有用的功能。