2010-02-19 16 views

Respuesta

-2

Si no me equivoco, la IP de la puerta de enlace siempre es la que sea la dirección IP de su dispositivo, con el último octeto configurado en "1", ¿no es así? Si eso es lo que está buscando, debería poder encontrar los consejos que necesita del archivo localhostAddresses.m que forma parte de las muestras en las fuentes de CocoaHTTPServer. Utilizo el proyecto para agregar un servidor web interno dentro de mi aplicación y obtengo la IP de los dispositivos de los métodos del archivo fuente.

Dr. Touch habla del tema at this link.

+5

Esto es incorrecto. Si bien es una convención común, colocar el enrutador en x.y.z.1 no es obligatorio ni está garantizado por la especificación. He visto muchas redes en vivo donde el enrutador era xyz254, y he visto redes en vivo donde la puerta de enlace predeterminada NO está en la subred del dispositivo (la mayoría de los sistemas operativos intentarán enviar a la dirección IP de la puerta de enlace sin condiciones si la IP a la que se envían es no enrutable, incluso si la puerta de enlace no se puede enrutar ... algunos ISP dependen de este comportamiento). Además, las cosas tienden a configurarse de manera diferente en las subredes Clase A y B. –

+0

Gracias por iluminarme. Espero (por curiosidad) escuchar lo que descubres. – wkw

0

Tuve éxito obteniendo la dirección del protocolo SSDP enviando un paquete UDP buscando el tipo de servicio "urn: schemas-upnp-org: dispositivo: InternetGatewayDevice: 1" y tomando nota del primer dispositivo (si hay alguno) que responde (ignorando la carga útil, ya que solo quiero la dirección IP de la puerta de enlace).

Esto funciona para mi aplicación, pero requiere que el enrutador implemente SSDP, que no es perfecto, aunque funciona en mi caso.

Dado que esta es una aplicación de iPhone para fines especiales (interna, solamente), me voy a ir con esto. No marcaré esto como "la respuesta" porque no es una solución de propósito general. Si vuelvo a esto y busco una solución de propósito general (como el uso de ICMP) o descubro cómo usar las API de configuración de SDK de iPhone para consultar esta información, publicaré aquí.

+1

Hola Bill, ¿Alguna sugerencia sobre el envío y la recepción de paquetes UDP? Me estoy perdiendo en los documentos en este momento y algo de claridad realmente ayudaría. Intento usar el iPhone para descubrir dispositivos SSDP y parece que ya has hecho eso. Saludos, Dave. –

7

He resuelto esto, aunque yo sé si esta solución es válida (no será rechazada por manzana)

primero te voy a dar las fuentes que utiliza para construir mi solución al:

http://code.google.com/p/doubango/source/browse/trunk/thirdparties/iphone/include/net/route.h?r=348

http://code.google.com/p/touchcode/source/browse/Experimental/TouchHTTPD/Externals/libnatpmp-20071213/getgateway.c?r=bc90b03205cbebb0633a7b5b203c2c6d5cb860dc

sería muy bueno para obtener alguna información si cree que apple va a permitir que este tipo de código.

getgateway.h

#ifndef __GETGATEWAY_H__ 
#define __GETGATEWAY_H__ 

/* getdefaultgateway() : 
* return value : 
* 0 : success 
* -1 : failure */ 
int getdefaultgateway(in_addr_t * addr); 

#endif 

getgateway.c

#include <stdio.h> 
#include <netinet/in.h> 
#include <stdlib.h> 
#include <sys/sysctl.h> 
#include "getgateway.h" 
#include "route.h" 
#include <net/if.h> 
#include <string.h> 

#define CTL_NET   4    /* network, see socket.h */ 


#if defined(BSD) || defined(__APPLE__) 

#define ROUNDUP(a) \ 
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 

int getdefaultgateway(in_addr_t * addr) 
{ 
    int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, 
     NET_RT_FLAGS, RTF_GATEWAY}; 
    size_t l; 
    char * buf, * p; 
    struct rt_msghdr * rt; 
    struct sockaddr * sa; 
    struct sockaddr * sa_tab[RTAX_MAX]; 
    int i; 
    int r = -1; 
    if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { 
     return -1; 
    } 
    if(l>0) { 
     buf = malloc(l); 
     if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { 
      return -1; 
     } 
     for(p=buf; p<buf+l; p+=rt->rtm_msglen) { 
      rt = (struct rt_msghdr *)p; 
      sa = (struct sockaddr *)(rt + 1); 
      for(i=0; i<RTAX_MAX; i++) { 
       if(rt->rtm_addrs & (1 << i)) { 
        sa_tab[i] = sa; 
        sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); 
       } else { 
        sa_tab[i] = NULL; 
       } 
      } 

      if(((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) 
       && sa_tab[RTAX_DST]->sa_family == AF_INET 
       && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) { 


       if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { 
         char ifName[128]; 
         if_indextoname(rt->rtm_index,ifName); 

         if(strcmp("en0",ifName)==0){ 

           *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; 
           r = 0;       
         } 
       } 
      } 
     } 
     free(buf); 
    } 
    return r; 
} 
#endif 
+0

192.168 no es el único espacio de direcciones IP reservado para redes privadas, por lo que la cláusula if que ha agregado es realmente perjudicial. Este código perderá las IP de la puerta de enlace en 10.x y 172.16.x, que son tan válidas como 192.168.x. Considera usar el código original en su lugar. – AriX

+0

Usar el código original como he sugerido puede causar problemas, ya que en un iPhone puede obtener la puerta de enlace de la red interna del operador en lugar de la de Wi-Fi. Supongo que es por eso que agregó el cheque para 192.168.x en primer lugar. Estoy trabajando en una forma de obtener el nombre de la interfaz para estas puertas de enlace, para que pueda verificar que la puerta de enlace corresponde a la interfaz de Wi-Fi. – AriX

+0

considere actualizar la respuesta una vez que encuentre una solución – Jakob

0

para aquellos que necesitan IP legible por humanos, he modificado mi getgateway.c de la siguiente manera:

añadir a incluye:

#include <arpa/inet.h> 

dentro de la última instrucción if, entre * addr yr = 0;

if(strcmp("en0",ifName)==0){ 

*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; 

char str[INET_ADDRSTRLEN]; 
inet_ntop(AF_INET, &(((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr), str, INET_ADDRSTRLEN); // supports IPv6 
printf("IP: %s\n", str); // prints "192.0.2.33" 

r = 0; 
} 
Cuestiones relacionadas