奇怪的InetAddress.isReachable()问题

我的工作是为零售环境开发适用于网络摄像机的软件。 我的团队正在开发的软件之一是一个网络服务器,它可以检索由摄像机本身(具有自己的嵌入式网络服务器)以HTML格式生成的各种报告并存储在摄像机上。 然后,我们的软件将从相机中获取这些报告并将其存储在中央网络服务器上。

虽然我们很好地将摄像机的IP插入到我们的软件中,但我正在开发一个简单的Java类,它将查询网络并找到网络上的所有摄像机。

但问题是,虽然它在我的PC和我的同事的PC上运行得很好,但是当我们尝试在将托管我们软件的实际网络服务器PC上运行它时…它会运行,但说子网中的每个IP都处于脱机状态/ unreachable除网关IP外。

例如,如果我在插入封闭的局域网时从我的PC或我的同事PC运行它,我会发现以下有效的IP以及一个告诉我它是否是相机的标志。 (网关是192.168.0.1,子网掩码是255.255.255.0,这意味着需要查找全部256个设备)

IP:/192.168.0.1 Active:true Camera:false IP:/192.168.0.100 Active:true Camera:true <- this is camera 1 IP:/192.168.0.101 Active:true Camera:true <- this is camera 2 IP:/192.168.0.103 Active:true Camera:false <- my PC IP:/192.168.0.104 Active:true Camera:false <- this is our webserver 

但出于某种原因,当使用相同的JRE从Web服务器PC运行相同的程序时,我只能找到以下内容

 IP:/192.168.0.1 Active:true Camera:false 

现在我的代码,而不是在主线程上按顺序枚举每个IP,而是为每个要检查的IP创建一个单独的线程并同时运行它们(否则在整个IP范围内枚举将花费21分钟以上)超时5000ms / IP)。 然后主线程反复每15秒重新运行这些IP扫描线程。

我已经检查过所有线程都在所有PC上运行完成,没有exception被抛出。 甚至证实没有线程被卡住。 每个线程从开始到完成大约需要5001到5050ms,那些具有活动IP的线程会更快完成(> 5000ms),所以我知道它在ipAddr.isReachable(5000)方法中正确等待了整整5000ms。

我和我的同事在这一点上很难过,而在我们的电脑上运行似乎可以达到那些活跃的IP,但是没有得到网络服务器PC的响应?

我们已经排除了防火墙问题,管理员访问问题等。唯一的区别是我们的网络服务器是嵌入式Win XP,我们的PC是Windows 7。

这让我们难过。 有什么想法吗?

下面是运行每个IP线程的代码:

 public void CheckIP() { new Thread() { @Override public void run() { try { isActive = ipAddr.isReachable(5000); if (isActive) { if (!isCamera) { isCamera = new IpHttpManager().GetResponse(ipAddr.toString()); } } else { isCamera = false; } } catch (Exception e) { e.printStackTrace(); } } }.start(); 

}

编辑:这是在确定基于网关和子网的范围后构建每个IP以检查的代码…

 for(int i=subMin; i<=subMax; i++) { byte[] ip = new byte[] {(byte)oct[0],(byte)oct[1],(byte)oct[2],(byte)i}; try { scanners[subCount] = new IpScan(InetAddress.getByAddress(ip)); subCount++; } catch (UnknownHostException e) { e.printStackTrace(); }} 

谢谢大家,但我从来没有弄清楚或找出为什么这种奇怪的事情发生了。 我检查的一切都不是原因,所以这个问题可以关闭。

无论如何,我最终完全解决了这个问题。 我没有使用InetAddress,而是通过JNA调用Windows库IPHLPAPI.DLL和WSOCK32.DLL,然后构建了自己的ICMP ping类。 这是我用过的……

 public interface InetAddr extends StdCallLibrary { InetAddr INSTANCE = (InetAddr) Native.loadLibrary("wsock32.dll", InetAddr.class); ULONG inet_addr(String cp); //in_addr creator. Creates the in_addr C struct used below } public interface IcmpEcho extends StdCallLibrary { IcmpEcho INSTANCE = (IcmpEcho) Native.loadLibrary("iphlpapi.dll", IcmpEcho.class); int IcmpSendEcho( HANDLE IcmpHandle, //Handle to the ICMP ULONG DestinationAddress, //Destination address, in the form of an in_addr C Struct defaulted to ULONG Pointer RequestData, //Pointer to the buffer where my Message to be sent is short RequestSize, //size of the above buffer. sizeof(Message) byte[] RequestOptions, //OPTIONAL!! Can set this to NULL Pointer ReplyBuffer, //Pointer to the buffer where the replied echo is written to int ReplySize, //size of the above buffer. Normally its set to the sizeof(ICMP_ECHO_REPLY), but arbitrarily set it to 256 bytes int Timeout); //time, as int, for timeout HANDLE IcmpCreateFile(); //win32 ICMP Handle creator boolean IcmpCloseHandle(HANDLE IcmpHandle); //win32 ICMP Handle destroyer } 

然后使用它们来创建以下方法……

 public void SendReply(String ipAddress) { final IcmpEcho icmpecho = IcmpEcho.INSTANCE; final InetAddr inetAddr = InetAddr.INSTANCE; HANDLE icmpHandle = icmpecho.IcmpCreateFile(); byte[] message = new String("thisIsMyMessage!".toCharArray()).getBytes(); Memory messageData = new Memory(32); //In C/C++ this would be: void *messageData = (void*) malloc(message.length); messageData.write(0, message, 0, message.length); //but ignored the length and set it to 32 bytes instead for now Pointer requestData = messageData; Pointer replyBuffer = new Memory(256); replyBuffer.clear(256); // HERE IS THE NATIVE CALL!! reply = icmpecho.IcmpSendEcho(icmpHandle, inetAddr.inet_addr(ipAddress), requestData, (short) 32, null, replyBuffer, 256, timeout); // NATIVE CALL DONE, CHECK REPLY!! icmpecho.IcmpCloseHandle(icmpHandle); } public boolean IsReachable () { return (reply > 0); } 

我的猜测是你的迭代逻辑确定不同的IP地址是基于不同的配置,因此你的电脑提取所有地址,但你的网络服务器没有。

尝试在构建ip地址列表的逻辑中添加debug以进行检查。