Java 奇数InetAddress.isReachable()问题
我的工作是为零售环境的网络摄像头开发软件。我的团队正在开发的软件之一是一个Web服务器,它检索摄像机本身(它有自己的嵌入式Web服务器)以HTML生成并存储在摄像机上的各种报告。然后,我们的软件将从摄像头获取这些报告,并将其存储在中央Web服务器上 虽然我们可以很好地将摄像头的IP插入到我们的软件中,但我正在开发一个简单的Java类,该类将查询网络并定位网络上的所有摄像头 但问题是,虽然它在我的电脑和同事的电脑上运行良好,但当我们尝试在实际的Web服务器PC上运行它时,它将承载我们的软件。。。它运行,但表示子网中的每个IP都脱机/无法访问,网关IP除外 例如,如果我从我的电脑或我的同事电脑上运行它,当我插入封闭的局域网时,我会发现以下活动IP以及一个标志,告诉我它是否是摄像头。 (网关为192.168.0.1,子网掩码为255.255.255.0,这意味着要查找的256个设备的完整范围) 现在,我的代码不是在主线程上按顺序枚举每个IP,而是为每个要检查的IP创建一个单独的线程并并发运行它们(否则,在5000ms/IP超时时枚举整个IP范围需要21分钟多一点)。然后,主线程每隔15秒反复运行这些IP扫描线程 我已经检查了所有的线程在所有的PC上运行到完成,没有抛出异常。甚至验证了没有任何线程被卡住。每个线程从开始到完成大约需要5001到5050毫秒,而那些具有活动IP的线程完成得更快(>5000毫秒),因此我知道它在ipAddr.isReachable(5000)方法中正确地等待了整个5000毫秒 我和我的同事在这一点上被难住了,当它在我们的PC上运行时,似乎可以很好地到达那些活动的IP,但却没有得到Web服务器PC的响应 我们排除了防火墙问题、管理员访问问题等。。唯一的区别是我们的Web服务器是嵌入式Win XP,而我们的电脑是Windows 7 这把我们难住了。你知道为什么吗 下面是运行每个IP线程的代码:Java 奇数InetAddress.isReachable()问题,java,multithreading,networking,inetaddress,Java,Multithreading,Networking,Inetaddress,我的工作是为零售环境的网络摄像头开发软件。我的团队正在开发的软件之一是一个Web服务器,它检索摄像机本身(它有自己的嵌入式Web服务器)以HTML生成并存储在摄像机上的各种报告。然后,我们的软件将从摄像头获取这些报告,并将其存储在中央Web服务器上 虽然我们可以很好地将摄像头的IP插入到我们的软件中,但我正在开发一个简单的Java类,该类将查询网络并定位网络上的所有摄像头 但问题是,虽然它在我的电脑和同事的电脑上运行良好,但当我们尝试在实际的Web服务器PC上运行它时,它将承载我们的软件。。。它
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();
}}
for(int i=subMin;i我的猜测是,确定不同ip地址的迭代逻辑基于不同的配置,因此您的pc会获取所有地址,但您的Web服务器不会
尝试在建立要检查的ip地址列表的逻辑中添加debug。谢谢大家,但我从来没有弄清楚或指出为什么会发生这种奇怪的情况。我检查的所有内容都不是原因,所以这个问题可以解决
在任何情况下,我最终完全解决了这个问题。我没有使用InetAddress,而是采用本机方式,通过JNA调用Windows库iphlapi.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);
}
您可以从Web服务器ping您的计算机吗?您是否使用Wireshark进行过任何网络跟踪?这是最好的起点。将其安装到服务器上,并确定数据包是否从正确的接口发出,以及是否有任何响应。我假定流量通过交换机传输到摄像头。将带有Wireshark的笔记本电脑连接到摄像头点击/镜像端口并查看数据包的去向。@BevynQ是的,我可以ping它。At Jim:我会检查一下。我也曾想过同样的事情,从Web服务器发送的数据包是不同的。或者你可以尝试我欣赏响应,但实际上,我不获取IP地址,我只获取网关和子网地址sk,然后手动构建每个IP地址以进行检查。如果我无法获取网关,它将默认为0.0.0.0并终止。由于我能够获取网关,它将继续运行。奇怪的是,当它运行扫描线程时,我从Web服务器上的网关获得响应,但没有其他地址,而在PC上,我从网关和所有活动IPs收到响应,但我确实调试了它构建IPs的部分,以及每个线程的开始和结束位置。将在上面添加我构建IPs的代码片段我知道这是一篇非常古老的文章,但ULONG来自哪里?什么是reply?reply看起来是从IcmpSendEch返回的into:对于ULONG,我只是把它变成了一个长的work@Jdban101哇,我的这篇帖子太老了!我想不起来为什么我只是用java int而不是MS的ULONG,但不管是哪种情况,它都应该是好的。实际上,我的回复只是一个DWORD,在我的机器上是一个32位无符号整数,它与java的int的32位大小相匹配,而对于简单的回复计数来说,空间已经足够了
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);
}