2010-04-20 29 views
28

Actualmente estoy buscando una forma portátil de obtener las direcciones IP locales. Debido a que estoy usando Boost de todos modos, pensé que sería una buena idea usar Boost.Asio para esta tarea.Obtener dirección IP local usando Boost.Asio

Hay varios ejemplos en la red que deberían ser el truco. Ejemplos:

Official Boost.Asio Documentation

Some Asian Page

me trataron ambos códigos con solo ligeras modificaciones. El código en Boost.Doc fue cambiado para no resolver "www.boost.org" sino "localhost" o mi nombre de host en su lugar. Para obtener el nombre de host, utilicé boost :: asio :: ip :: host_name() o lo escribí directamente como una cadena.

Además, escribí mi propio código que era una fusión de los ejemplos anteriores y mi (pequeño) conocimiento que recopilé de la Documentación de Boost y otros ejemplos.

Todas las fuentes trabajadas, sino que se limitaron a devolver el siguiente IP:
127.0.1.1 (Eso no es un error tipográfico, su .1.1 al final)
corro y compilan el código en Ubuntu 9.10 con GCC 4.4 0.1

un colega intentó el mismo código en su máquina y se
127.0.0.2 (no es un error demasiado ...)
Se compila y ejecuta en Suse 11.0 con GCC 4.4.1 (no estoy 100% seguro)

No sé si es posible cambiar el localhost (1 27.0.0.1), pero sé que ni mi compañero ni yo lo hicimos. ifconfig dice que loopback usa 127.0.0.1. ifconfig también encuentra la IP pública que estoy buscando (141.200.182.30 en mi caso, la subred es 255.255.0.0)

¿Esto es un problema de Linux y el código no es tan portátil como pensaba? ¿Tengo que cambiar algo más o Boost.Asio no funciona como una solución para mi problema en absoluto?

Sé que hay muchas preguntas sobre temas similares en Stackoverflow y otras páginas, pero no puedo encontrar información que sea útil en mi caso. Si tienes enlaces útiles, sería bueno si pudieras señalarlo.

PS: Este es el código modificado he usado desde Boost.Doc:

#include <boost/asio.hpp> 
using boost::asio::ip::tcp;  

boost::asio::io_service io_service; 
tcp::resolver resolver(io_service); 
tcp::resolver::query query(boost::asio::ip::host_name(), ""); 
tcp::resolver::iterator iter = resolver.resolve(query); 
tcp::resolver::iterator end; // End marker. 
while (iter != end) 
{ 
    tcp::endpoint ep = *iter++; 
    std::cout << ep << std::endl; 
} 
+13

AFAIK, ASIO no proporciona una manera de enumerar las interfaces de su máquina (SIOCGIFCONF ioctl en Linux o GetAdaptersAddresses en Windows), que es, aparentemente, lo que está buscando. El código que muestra consulta el DNS con el nombre de host de su máquina, que no es lo mismo, y es menos robusto ya que depende más de la configuración de su red (en particular, el DNS tiene que "conocer" el nombre de su máquina). –

+0

¿Asio :: ip :: address_v4 :: loopback() satisface sus necesidades? – yanpas

Respuesta

4

Si edita el archivo/etc/hosts (esto es * nix solamente, podría funcionar para ventanas también ... No estoy seguro) usted puede corregir este problema.

Dentro de los anfitriones archivo que encontrará algo como: (esto es Ubuntu, tenga en cuenta la 1.1)

127.0.0.1 localhost 127.0.1.1
yourPcName.yourNetwork.tld

si cambia este presentar a

127.0.0.1 localhost 127.0.1.1
yourPcName.yourNetwork.tld
your.real.ip.here yourPcName

, entonces el nombre de host debería resolverse correctamente.

Un método para probar la resolución adecuada es con el comando "hostname -i" que debe imprimir su dirección IP incorrectamente antes de cambiar los hosts, y luego correctamente.

Por supuesto, esta es una solución terrible para direcciones IP dinámicas ... eh.

+1

Gracias por esta pista. Aparentemente Boost.Asio simplemente está leyendo estos valores cuando usa un * nix-system. Me funcionó con Ubuntu 9.10, 10.04 y Suse 11.2. – MOnsDaR

6

Este es un truco que aprendí de la programación en red de python (google) para descubrir la dirección IP de mi máquina. Esto solo funciona si tienes una conexión a Internet y puedes conectarte a google.com y me da la dirección privada 192.168.x.x de mi máquina doméstica.

try { 
    boost::asio::io_service netService; 
    udp::resolver resolver(netService); 
    udp::resolver::query query(udp::v4(), "google.com", ""); 
    udp::resolver::iterator endpoints = resolver.resolve(query); 
    udp::endpoint ep = *endpoints; 
    udp::socket socket(netService); 
    socket.connect(ep); 
    boost::asio::ip::address addr = socket.local_endpoint().address(); 
    std::cout << "My IP according to google is: " << addr.to_string() << std::endl; 
} catch (std::exception& e){ 
    std::cerr << "Could not deal with socket. Exception: " << e.what() << std::endl; 

} 
+3

Eso es ** no ** su IP de acuerdo con google ... Es la IP de una interfaz configurada en su máquina. – unixman83

+1

Es lo que necesitamos para la dirección IP local. Como @MOnsDaR dice el que devolvió ifconfig/ipconfig. Funciona para mi caso especial cuando tengo otra máquina para conectarme. – fantastory

5

Puede encontrar "su" dirección con el código que ha publicado. PERO ... se vuelve complicado. Puede haber múltiples NIC, puede haber direcciones LAN y WAN, cableadas e inalámbricas, loopback ... En mi escritorio tenía una NIC pero dos ips aquí de dos servidores DHCP diferentes en mi lan ...

Encontré era mejor dejar que el usuario proporcionara la IP para enlazar como un parámetro de línea de comando. Y sí, ¡esa es una solución portátil! :-)

Cuestiones relacionadas