multiples - socket programming java
Odd InetAddress.isReachable() problema (2)
Supongo que su lógica de iteración para determinar la dirección IP diferente se basa en una configuración diferente, por lo tanto, su PC obtiene todas las direcciones, pero su servidor web no.
Intente agregar la depuración en la lógica donde crea la lista de direcciones IP para verificar.
Mi trabajo es desarrollar software para cámaras con capacidad de red para entornos minoristas. Uno de los aspectos de software que mi equipo está desarrollando es un servidor web que recupera varios informes generados en HTML por la propia cámara (que tiene su propio servidor web incorporado) y se almacena en la cámara. Nuestro software OBTENDRÁ estos informes de la cámara y los almacenará en un servidor web central.
Si bien estamos conectando las IP de las cámaras a nuestro software, estoy desarrollando una clase Java simple que consultará la red y localizará todas las cámaras en la red.
El problema es que aunque funciona bien en mi PC y en la PC de mi compañero de trabajo, cuando intentamos ejecutarlo en la PC del servidor web real que alojará nuestro software ... se ejecuta, pero dice que cada IP de la subred está fuera de línea. / inalcanzable EXCEPTO para la puerta de enlace IP.
Por ejemplo, si lo ejecuto desde mi PC o la PC de mis compañeros de trabajo cuando estoy conectado a la LAN cerrada, obtengo las siguientes direcciones IP activas junto con una bandera que me dice si es una cámara o no. (la puerta de enlace es 192.168.0.1, la máscara de subred es 255.255.255.0, lo que significa que debe buscarse un rango completo de 256 dispositivos)
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
Pero por alguna razón, cuando ejecuto el mismo programa desde la PC del servidor web, usando el mismo JRE, solo consigo encontrar lo siguiente
IP:/192.168.0.1 Active:true Camera:false
Ahora mi código, en lugar de enumerar cada IP en orden en el subproceso principal, crea un subproceso separado para cada IP que se va a verificar y ejecuta al mismo tiempo (de lo contrario, tomaría poco más de 21 minutos enumerar todo el rango de IP en un tiempo de espera de 5000ms / IP). El subproceso principal luego vuelve a ejecutar estos subprocesos de exploración de IP cada 15 segundos una y otra vez.
Comprobé que todos los hilos están en ejecución en todas las PC, sin excepciones. Incluso verificó que ninguno de los hilos se estanca. Cada subproceso tarda aproximadamente de 5001 a 5050 ms desde el inicio hasta que finaliza, y los subprocesos que tienen un IP activo finalizan antes (> 5000 ms), por lo que sé que está esperando correctamente los 5000 ms completos en el método ipAddr.isReachable (5000).
Mi compañero de trabajo y yo estamos perplejos en este momento, mientras que parece alcanzar esas PI activas cuando se ejecutan en nuestras PC, sin obtener ninguna respuesta de la PC del servidor web ???
Hemos descartado problemas de firewall, problemas de acceso de administrador, etc. La única diferencia es que nuestro servidor web es Embedded Win XP, y nuestras PC son Windows 7.
Esto nos tiene perplejos. ¿Alguna idea de por qué?
A continuación se muestra el código que ejecuta cada subproceso de 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();
}
EDITAR: Aquí está el código que construye cada IP para verificar después de determinar el rango basado en la puerta de enlace y la subred ...
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();
}}
Gracias a todos, pero nunca me di cuenta o identifiqué por qué esta rareza estaba sucediendo. Todo lo que revisé no fue la causa, por lo que esta pregunta se puede cerrar.
En cualquier caso, terminé trabajando en torno a eso por completo. En lugar de usar InetAddress, acabo de convertirme en nativo y construí mi propia clase de ping ICMP, a través de JNA, invocando las bibliotecas de Windows IPHLPAPI.DLL y WSOCK32.DLL. Esto es lo que usé ...
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
}
Y luego usarlos para crear el siguiente método ...
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);
}