当前位置: 首页 > 面试题库 >

奇数InetAddress.isReachable()问题

刘阳荣
2023-03-14
问题内容

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

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

但是问题是,尽管它可以在我的PC和同事的PC上正常运行,但是当我们尝试在将托管我们软件的实际Web服务器PC上运行它时……却在运行,但是说子网中的每个IP都处于脱机状态/网关IP不可访问。

例如,如果在插入封闭的LAN时从我的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分钟的时间。超时时间为5000毫秒/
IP)。然后,主线程每隔15秒钟反复运行这些IP扫描线程。

我检查了所有线程在所有PC上的运行是否都已完成,没有异常被抛出。甚至验证没有任何线程被卡住。每个线程从开始到完成大约需要5001到5050毫秒,而那些拥有活动IP的线程会更快地完成(>
5000毫秒),因此我知道它在ipAddr.isReachable(5000)方法中正确等待了完整的5000毫秒。

我和我的同事在这一点上感到很沮丧,虽然在我们的PC上运行时似乎可以达到那些活动IP的罚款,但是Web服务器PC却没有任何响应?

我们已经排除了防火墙问题,管理员访问问题等。唯一的区别是我们的Web服务器是Embedded 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);
}


 类似资料:
  • 问题内容: 我试图找出网络上的特定主机是否可以访问。我的java代码如下: 这工作得很好,但是如果我将超时降低为500ms,它将不再指定可访问的主机。我计划在一个循环中检查很多主机,因此低超时非常重要。如果我从Windows命令行手动ping主机,则所需时间少于10ms。 那么,为什么Java方法需要更高的超时才能成功?有使用的替代方法吗? 问题答案: 这取决于您所指的可达性。如果仅找到在特定端口

  • 例如,如果第一个< code > CharAt(0)= ' w ' ,我正在处理从用户输入得到的输出,以便只显示奇数或偶数。 它是否通过“System.out.println(CharAt(0)CharAt 2)CharAt(4))”工作? 我正在使用扫描仪项目获得用户输入,并已经有以下输入部分: 有没有办法只拥有像(0 奇数)这样的公式?

  • 问题内容: 我的NPE的Stacktrace开头为: 该文件中的行号141为: 其中store不为null且store.getAvailablePieces()为null。我不明白为什么我要在这里例外。 有任何想法吗? 问题答案: 我99%确信这是由于条件运算符的行为引起的。我相信您的代码等同于: 换句话说,它会将的结果拆箱到,然后再装箱到。如果返回,的确会导致死亡。 解决方法是也使第三个操作数:

  • 我们的教授在一个文本文件中给了我们一份982个数字的列表,我们已经阅读了文件中的文本,并打印出了一些关于数字的信息。到目前为止,除了奇数的总数之外,我的一切都是正确的(她给了我们正确的答案)。我不知道如何得到奇数的平均值,即48201.56。 我一直得到的结果是97354,这很奇怪,因为我用的方法和所有数字的平均值和偶数的平均值是一样的。 我想知道为什么“总平均数”的答案不是48201.56。谢谢

  • 我正试图计算逆FFT,因为我只想要选择频率。下面是我如何进行FFT: 正如上面所看到的,我正在从每个点做一个复数。 然后,我计算一个频率的功率电平:

  • 问题内容: 这是目录树: 在main.go中: 在client_test.go中: 错误: 我已经阅读了如何在golang中使用自定义软件包?而且我认为我有和这个人一样的解决方案,但是我只是不知道如何解决这个问题。请帮忙。 去环境: 问题答案: 命令去,测试包。 名称与文件模式“ * _test.go”匹配的文件可以包含测试函数,基准函数和示例函数。 不要使用保留名称。例如,将与贯穿始终。