2013-09-26 25 views
3

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

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

但问题是,虽然它在我的PC和我的同事的个人电脑上运行得很好,但是当我们尝试在将托管我们的软件的实际网络服务器PC上运行时...它运行,但是说每个IP除网关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 

但由于某些原因,从运行的网络服务器PC相同的程序时,使用同样的JRE,我只得到以下发现

IP:/192.168.0.1 Active:true Camera:false 

现在我的代码,而不是通过每一个IP,以便在主线程枚举,而不是创建一个单独的线程用于进行检查每个IP,并同时运行它们(否则在5000ms/IP的超时时间内枚举整个IP范围将花费超过21分钟)。主线程然后每隔15秒重复运行这些IP扫描线程。

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

我和我的同事在这一点上很难过,虽然它似乎在我们的PC上运行时达到了那些活跃的IP,但是却没有从网络服务器PC得到回应?

我们已经排除了防火墙问题,管理员权限的问题,等等。唯一的区别是,我们的Web服务器嵌入式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(); 
}} 
+0

可以从你的网络服务器ping您的机器吗? – BevynQ

+0

你使用Wireshark做过任何网络跟踪吗?这是最好的起点。将它安装在服务器上,并确定数据包是否发送到正确的接口,以及是否有任何响应。我想流量正在通过切换到相机。将一台带有Wireshark的笔记本电脑连接到tap/mirror端口并查看数据包的位置。 –

+0

@BevynQ是的,我可以ping它。在吉姆:将检查出来。我也曾想过同样的事情,即从Web服务器发送的数据包是不同的。 – Jgregoire108

回答

4

谢谢大家,但我从来没有弄清楚或明确为什么会出现这种奇怪现象。我检查过的所有东西都不是原因,所以这个问题可以关闭。

无论如何,我最终完全解决了这个问题。我不是使用InetAddress,而是通过JNA调用Windows库IPHLPAPI.DLL和WSOCK32.DLL,而不是使用InetAddress,而是通过本机构建自己的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); 
} 
+0

我知道这是一个超级老的帖子,但ULONG从哪里来?什么是答复? – Jdban101

+0

答复看起来是从IcmpSendEcho返回的一个int:https://msdn.microsoft.com/en-us/library/windows/desktop/aa366050%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 ULONG,我只是把它变成一个很长,它似乎工作 – Jdban101

+0

@ Jdban101 哇,我的这篇文章是旧的!我不记得为什么我只是用java int而不是MS的ULONG,但无论如何,它应该没问题。实际上的回复只是一个DWORD,它在我的机器上是一个32位无符号整数,它与java的int的32位大小相匹配,无论如何这都足够空间用于简单计数的回复 – Jgregoire108

0

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

尝试添加调试在您建立ip地址列表检查的逻辑。

+0

我很欣赏这种回应,但实际上,我不取IP地址,我只取网关和子网掩码,然后手动建立每个IP地址来检查那里。 如果我无法获取网关,它将默认为0.0.0.0并终止。由于我能够获得网关,它将继续运行。奇怪的部分是,当它运行扫描线程时,我得到网络服务器上的网关的响应,但没有其他地址,而在PC上,我得到来自网关和所有活动IP的响应 – Jgregoire108

+0

但我做了调试那部分它建立IP,以及调试每个线程开始和结束的地方。将添加一个代码片段,我在哪里建立IP以上 – Jgregoire108