Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 奇数InetAddress.isReachable()问题_Java_Multithreading_Networking_Inetaddress - Fatal编程技术网

Java 奇数InetAddress.isReachable()问题

Java 奇数InetAddress.isReachable()问题,java,multithreading,networking,inetaddress,Java,Multithreading,Networking,Inetaddress,我的工作是为零售环境的网络摄像头开发软件。我的团队正在开发的软件之一是一个Web服务器,它检索摄像机本身(它有自己的嵌入式Web服务器)以HTML生成并存储在摄像机上的各种报告。然后,我们的软件将从摄像头获取这些报告,并将其存储在中央Web服务器上 虽然我们可以很好地将摄像头的IP插入到我们的软件中,但我正在开发一个简单的Java类,该类将查询网络并定位网络上的所有摄像头 但问题是,虽然它在我的电脑和同事的电脑上运行良好,但当我们尝试在实际的Web服务器PC上运行它时,它将承载我们的软件。。。它

我的工作是为零售环境的网络摄像头开发软件。我的团队正在开发的软件之一是一个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线程的代码:

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);
}