我维护了一个用于将软件部署到嵌入式设备的工具。通过不断扫描端口22上应答的任何IP地址,然后打开到该端口的SSH连接来检测这些设备。
在Linux和Windows 7上,此过程适用于20个线程,并且套接字连接上的超时为500毫秒。
不幸的是,我们的某些用户仍然使用Windows XP,而这些设置根本不起作用。具有3000ms超时的单个线程似乎可靠地工作,将线程增加到两个或将超时设置为1000ms会导致一致的故障检测到任何事情 - 所有尝试连接超时(SocketTimeoutException)。
我们尝试在其中一台计算机上应用Event ID 4226 Patcher,但这没有帮助。我们也无法在日志中看到这些事件。
导致此行为的原因是什么,我有什么方法可以解决这个问题?
编辑:用于连接的实际代码是:
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(address, 22), PORT_SCAN_TIMEOUT);
LOGGER.trace("Someone is listening on {}:22", address);
} catch (Throwable t) {
LOGGER.trace("Failed scan on {}", address, t);
reschedule(address);
continue;
}
如果此连接成功,则使用JSch创建一个全新的连接。在失败场景中,代码永远不会超出此初始尝试。记录的所有异常都是SocketTimeoutExceptions。
编辑2 :
我尝试在堆栈中降低一级,只检查主机是否存在,而不是服务器套接字,用以下代码替换上面的代码:
try {
if(!InetAddresses.forString(address).isReachable(PORT_SCAN_TIMEOUT)) {
LOGGER.trace("{} not reachable", address);
reschedule(address);
continue;
}
} catch (IOException e) {
LOGGER.warn("Error trying to check host presence on {}, we will try to connect", e, address);
}
如果由多个线程或快速运行,即使这会失败,但是使用单个线程和3000毫秒超时。针对主机的命令行ping直接返回成功(现在将成为我的后备解决方案)。
编辑3 :
有了它,它按预期工作(显然只在Windows上):
ProcessBuilder builder = new ProcessBuilder("ping", "-n", "1", address);
try {
Process process = builder.start();
process.waitFor();
return process.exitValue() == 0;
} catch (Throwable t) {
LOGGER.error("Failed to spawn ping process", t);
return false;
}
鉴于受影响的机器数量很少,我将使用它,由魔术系统属性切换触发。我仍然对前两种方法可能失败的原因提出任何建议。
答案 0 :(得分:0)
似乎Windows XP限制了单个进程可以建立的连接数。我的解决方案是应用the nmap page for Windows中描述的注册表更改。之后程序按预期运行。