c++ - saber - para que sirve la direccion ip de un celular
Obtener la dirección IP de la computadora local (12)
de torial: si usa winsock, aquí hay una forma: http://tangentsoft.net/wskfaq/examples/ipaddr.html
En cuanto a la parte de la subred de la pregunta; no hay una forma de agnóstico de plataforma para recuperar la máscara de subred ya que la API de socket POSIX (que implementan todos los sistemas operativos modernos) no especifica esto. Por lo tanto, deberá usar cualquier método disponible en la plataforma que esté utilizando.
En C ++, ¿cuál es la forma más fácil de obtener la dirección IP y la máscara de subred de la computadora local?
Quiero poder detectar la dirección IP de la máquina local en mi red local. En mi caso particular, tengo una red con una máscara de subred de 255.255.255.0 y la dirección IP de mi computadora es 192.168.0.5. Necesito obtener estos dos valores programáticamente para enviar un mensaje de difusión a mi red (en el formulario 192.168.0.255, para mi caso particular)
Editar: Muchas respuestas no dieron los resultados que esperaba porque tenía dos IP de red diferentes. El código de Torial hizo el truco (me dio ambas direcciones IP). Gracias.
Editar 2: Gracias a Brian R. Bondy por la información sobre la máscara de subred.
No puedes hacer eso en Estándar C ++.
Estoy publicando esto porque es la única respuesta correcta. Su pregunta le pregunta cómo hacerlo en C ++. Bueno, no puedes hacerlo en C ++. Puede hacerlo en Windows, POSIX, Linux, Android, pero todas esas son soluciones específicas de sistema operativo y no forman parte del estándar de lenguaje.
El estándar C ++ no tiene una capa de red en absoluto.
Supongo que tiene esta suposición equivocada de que C ++ Standard define el mismo alcance de funciones que otros estándares de lenguaje, Java. Si bien Java puede tener una red integrada (e incluso un marco de GUI) en la biblioteca estándar propia del lenguaje, C ++ no lo hace.
Si bien hay API y bibliotecas de terceros que pueden ser utilizadas por un programa C ++, esto de ninguna manera es lo mismo que decir que puede hacerlo en C ++.
Aquí hay un ejemplo para aclarar a qué me refiero. Puede abrir un archivo en C ++ porque tiene una clase fstream
como parte de su biblioteca estándar. Esto no es lo mismo que usar CreateFile()
, que es una función específica de Windows y está disponible solo para WINAPI.
¿No puedes enviarlo a INADDR_BROADCAST ? Es cierto que eso enviará todas las interfaces, pero eso rara vez es un problema.
De lo contrario, ioctl y SIOCGIFBRDADDR deberían darle la dirección en * nix, y WSAIoctl en win32.
Además, tenga en cuenta que "la IP local" podría no ser una cosa particularmente única. Si se encuentra en varias redes físicas (cableadas + inalámbricas + bluetooth, por ejemplo, o un servidor con muchas tarjetas Ethernet, etc.) o tiene configuradas las interfaces TAP / TUN, su máquina puede tener fácilmente una gran cantidad de interfaces.
El problema con todos los enfoques basados en gethostbyname es que no obtendrá todas las direcciones IP asignadas a una máquina en particular. Los servidores generalmente tienen más de un adaptador.
Aquí hay un ejemplo de cómo puede iterar a través de todas las direcciones Ipv4 e Ipv6 en la máquina host:
void ListIpAddresses(IpAddresses& ipAddrs)
{
IP_ADAPTER_ADDRESSES* adapter_addresses(NULL);
IP_ADAPTER_ADDRESSES* adapter(NULL);
// Start with a 16 KB buffer and resize if needed -
// multiple attempts in case interfaces change while
// we are in the middle of querying them.
DWORD adapter_addresses_buffer_size = 16 * KB;
for (int attempts = 0; attempts != 3; ++attempts)
{
adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(adapter_addresses_buffer_size);
assert(adapter_addresses);
DWORD error = ::GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_FRIENDLY_NAME,
NULL,
adapter_addresses,
&adapter_addresses_buffer_size);
if (ERROR_SUCCESS == error)
{
// We''re done here, people!
break;
}
else if (ERROR_BUFFER_OVERFLOW == error)
{
// Try again with the new size
free(adapter_addresses);
adapter_addresses = NULL;
continue;
}
else
{
// Unexpected error code - log and throw
free(adapter_addresses);
adapter_addresses = NULL;
// @todo
LOG_AND_THROW_HERE();
}
}
// Iterate through all of the adapters
for (adapter = adapter_addresses; NULL != adapter; adapter = adapter->Next)
{
// Skip loopback adapters
if (IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
{
continue;
}
// Parse all IPv4 and IPv6 addresses
for (
IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
NULL != address;
address = address->Next)
{
auto family = address->Address.lpSockaddr->sa_family;
if (AF_INET == family)
{
// IPv4
SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
char str_buffer[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, &(ipv4->sin_addr), str_buffer, INET_ADDRSTRLEN);
ipAddrs.mIpv4.push_back(str_buffer);
}
else if (AF_INET6 == family)
{
// IPv6
SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);
char str_buffer[INET6_ADDRSTRLEN] = {0};
inet_ntop(AF_INET6, &(ipv6->sin6_addr), str_buffer, INET6_ADDRSTRLEN);
std::string ipv6_str(str_buffer);
// Detect and skip non-external addresses
bool is_link_local(false);
bool is_special_use(false);
if (0 == ipv6_str.find("fe"))
{
char c = ipv6_str[2];
if (c == ''8'' || c == ''9'' || c == ''a'' || c == ''b'')
{
is_link_local = true;
}
}
else if (0 == ipv6_str.find("2001:0:"))
{
is_special_use = true;
}
if (! (is_link_local || is_special_use))
{
ipAddrs.mIpv6.push_back(ipv6_str);
}
}
else
{
// Skip all other types of addresses
continue;
}
}
}
// Cleanup
free(adapter_addresses);
adapter_addresses = NULL;
// Cheers!
}
En DEV C ++, utilicé C puro con WIN32, con este fragmento de código:
case IDC_IP:
gethostname(szHostName, 255);
host_entry=gethostbyname(szHostName);
szLocalIP = inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
//WSACleanup();
writeInTextBox("/n");
writeInTextBox("IP: ");
writeInTextBox(szLocalIP);
break;
Cuando hago clic en el botón ''mostrar ip'', funciona. Pero en la segunda vez, el programa se cierra (sin advertencia ni error). Cuando lo hago:
//WSACleanup();
El programa no se cierra, incluso haciendo clic en el mismo botón varias veces con la velocidad más rápida. Entonces WSACleanup () puede no funcionar bien con Dev-C ++.
La pregunta es más complicada de lo que parece, porque en muchos casos no hay "una dirección IP para la computadora local" sino una cantidad de direcciones IP diferentes. Por ejemplo, la Mac en la que estoy escribiendo ahora (que es una configuración de Mac estándar muy básica) tiene las siguientes direcciones IP asociadas a ella:
fe80::1%lo0
127.0.0.1
::1
fe80::21f:5bff:fe3f:1b36%en1
10.0.0.138
172.16.175.1
192.168.27.1
... y no se trata solo de averiguar cuál de los anteriores es "la dirección IP real", tampoco ... todos son "reales" y útiles; algunos más útiles que otros dependiendo de para qué vas a usar las direcciones.
En mi experiencia, a menudo la mejor manera de obtener "una dirección IP" para su computadora local no es consultar la computadora local, sino preguntarle a la computadora que su programa está hablando con lo que ve en la dirección IP de su computadora. por ejemplo, si está escribiendo un programa de cliente, envíe un mensaje al servidor pidiéndole al servidor que envíe como datos la dirección IP de la que proviene su solicitud. De esta forma sabrá cuál es la dirección IP relevante , dado el contexto de la computadora con la que se está comunicando.
Dicho esto, ese truco puede no ser apropiado para algunos fines (por ejemplo, cuando no se está comunicando con una computadora en particular), por lo que a veces solo necesita reunir la lista de todas las direcciones IP asociadas a su máquina. La mejor manera de hacerlo en Unix / Mac (AFAIK) es llamando a getifaddrs () e iterando sobre los resultados. En Windows, pruebe GetAdaptersAddresses () para obtener una funcionalidad similar. Por ejemplo, los usos de ambos, vea la función GetNetworkInterfaceInfos () en este archivo .
Pude hacerlo utilizando el servicio DNS bajo VS2013 con el siguiente código:
#include <Windns.h>
WSADATA wsa_Data;
int wsa_ReturnCode = WSAStartup(0x101, &wsa_Data);
gethostname(hostName, 256);
PDNS_RECORD pDnsRecord;
DNS_STATUS statsus = DnsQuery(hostName, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsRecord, NULL);
IN_ADDR ipaddr;
ipaddr.S_un.S_addr = (pDnsRecord->Data.A.IpAddress);
printf("The IP address of the host %s is %s /n", hostName, inet_ntoa(ipaddr));
DnsRecordListFree(&pDnsRecord, DnsFreeRecordList);
Tuve que agregar Dnsapi.lib como dependencia adiccional en la opción del enlazador.
Referencia here .
Puede usar gethostname seguido de gethostbyname para obtener su IP interna de la interfaz local.
Sin embargo, esta IP devuelta puede ser diferente de su IP externa. Para obtener su IP externa, tendría que comunicarse con un servidor externo que le dirá cuál es su IP externa. Porque la IP externa no es tuya, pero son tus enrutadores.
//Example: b1 == 192, b2 == 168, b3 == 0, b4 == 100
struct IPv4
{
unsigned char b1, b2, b3, b4;
};
bool getMyIP(IPv4 & myIP)
{
char szBuffer[1024];
#ifdef WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
if(::WSAStartup(wVersionRequested, &wsaData) != 0)
return false;
#endif
if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
struct hostent *host = gethostbyname(szBuffer);
if(host == NULL)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
//Obtain the computer''s IP
myIP.b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;
myIP.b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;
myIP.b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;
myIP.b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;
#ifdef WIN32
WSACleanup();
#endif
return true;
}
También siempre puede usar 127.0.0.1 que representa la máquina local siempre.
Máscara de subred en Windows:
Puede obtener la máscara de subred (y la puerta de enlace y otra información) consultando las subclaves de esta entrada de registro:
HKEY_LOCAL_MACHINE / SYSTEM / CurrentControlSet / Services / Tcpip / Parameters / Interfaces
Busque el valor de registro SubnetMask.
Otros métodos para obtener información de interfaz en Windows:
También puede recuperar la información que está buscando utilizando: WSAIoctl con esta opción: SIO_GET_INTERFACE_LIST
Sugiero mi código
DllExport void get_local_ips(boost::container::vector<wstring>& ips)
{
IP_ADAPTER_ADDRESSES* adapters = NULL;
IP_ADAPTER_ADDRESSES* adapter = NULL;
IP_ADAPTER_UNICAST_ADDRESS* adr = NULL;
ULONG adapter_size = 0;
ULONG err = 0;
SOCKADDR_IN* sockaddr = NULL;
err = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, NULL, &adapter_size);
adapters = (IP_ADAPTER_ADDRESSES*)malloc(adapter_size);
err = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, adapters, &adapter_size);
for (adapter = adapters; NULL != adapter; adapter = adapter->Next)
{
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue; // Skip Loopback
if (adapter->OperStatus != IfOperStatusUp) continue; // Live connection only
for (adr = adapter->FirstUnicastAddress;adr != NULL; adr = adr->Next)
{
sockaddr = (SOCKADDR_IN*)(adr->Address.lpSockaddr);
char ipstr [INET6_ADDRSTRLEN] = { 0 };
wchar_t ipwstr[INET6_ADDRSTRLEN] = { 0 };
inet_ntop(AF_INET, &(sockaddr->sin_addr), ipstr, INET_ADDRSTRLEN);
mbstowcs(ipwstr, ipstr, INET6_ADDRSTRLEN);
wstring wstr(ipwstr);
if (wstr != "0.0.0.0") ips.push_back(wstr);
}
}
free(adapters);
adapters = NULL; }
Winsock específico:
// Init WinSock
WSADATA wsa_Data;
int wsa_ReturnCode = WSAStartup(0x101,&wsa_Data);
// Get the local hostname
char szHostName[255];
gethostname(szHostName, 255);
struct hostent *host_entry;
host_entry=gethostbyname(szHostName);
char * szLocalIP;
szLocalIP = inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
WSACleanup();
Cómo obtener la dirección IP de la máquina local en la red parece describir la solución bastante bien ...