2008-11-25 85 views

Respuesta

45

es posible que desee el inet_pton, que devuelve -1 para el argumento AF no válido, 0 para la dirección no válida y +1 para la dirección IP válida. Es compatible tanto con IPv4 como con las direcciones IPv6 futuras. Si aún necesita escribir su propia dirección IP, recuerde que una norma El número hexadecimal de 32 bits es una dirección IP válida. No todas las direcciones IPv4 están en notación decimal con puntos.

Esta función comprueba la dirección y también le permite utilizar la misma dirección en llamadas de socket relacionadas.

+0

Gracias por responder. Terminé escribiendo un contenedor alrededor de inet_pton. Ver mi respuesta para la implementación (realmente simple). –

+1

** ADVERTENCIA **. De acuerdo con los documentos, devuelve -1 para el argumento AF no válido, 0 para la dirección no válida y +1 para la dirección IP válida. –

+0

¿Funcionará esto en plataformas Windows y Linux? – impulse

2

Boost.Regex sería apropiado.

bool validate_ip_address(const std::string& s) 
{ 
    static const boost::regex e("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); 
    return regex_match(s, e); 
} 
+0

del todo correcta, porque no verifica que los números están en el rango válido, pero eso no debería ser demasiado difícil de arreglar. –

+0

En realidad, consultar los números en un rango válido es bastante complicado en expresiones regulares. Vea la respuesta de Ferruccio para la expresión regular corregida. –

+0

Puede usar REGEX para extraer cada uno de los números, y luego verificar cada conjunto de dígitos para asegurarse de que esté en el rango apropiado. Esto puede ser más útil si desea evitar que las personas ingresen direcciones IP a las que no se puede acceder desde el mundo exterior, como 127.0.0.1 – Kibbee

2

Si quería escribir esto mismo en lugar de utilizar una biblioteca continuación

atoi() para convertir los caracteres a enteros se permitirá probar el rango de cada número, y algunas STRCMP de entre el " . "'s. También puede hacer algunas comprobaciones rápidas, como la longitud de la cadena (debe tener menos de 16 caracteres (sin incluir el terminador nulo), número de puntos. Etc.

Pero probablemente sea MUCHO más fácil de usar el código existente.

1

Si no desea que la sobrecarga de aumento o TR1 puede buscar los puntos y comprobar si los personajes entre ellos son los números del 0 al 255.

8

Aquí hay un método sencillo.

bool IsIPAddress(std::string & ipaddr) 
    {  

    StringTokenizer quads(ipaddr,"."); 

    if (quads.countTokens() != 4) return false; 

    for (int i=0; i < 4; i++) 
     { 
     std::string quad = quads.nextToken(); 
     for (int j=0; j < quad.length(); j++ 
     if (!isdigit(quad[j])) return false; 

     int quad = atoi(quads.GetTokenAt(i)); 
     if (quad < 0) || (quad > 255)) return false; 
     } 

    return true; 
    } 
+1

¿De qué biblioteca proviene la clase StringTokenizer? –

+19

Hay muchos por ahí, o puede implementar los suyos. Esta es una muy buena que puede descargar: http://www.partow.net/programming/stringtokenizer/index.html (asegúrese de que los términos de la licencia sean aceptables para su proyecto) – Steve

16

Esto se ve engañosamente simple pero tiene algunas trampas. Por ejemplo, muchas de las soluciones publicadas en las respuestas anteriores suponen que los quads están en la base 10, pero un quad que comience con debe ser tratado como un número base 8 (octal), por lo tanto, por ejemplo cualquier cuadrante que comience por cero y que contiene los dígitos 8 o 9 no es válido. Es decir, el número IP es 192.168.1.010no192.168.1.10 pero en realidad es 192.168.1.8, y el número IP 192.168.019.14 no es válida desde el tercer quad contiene la base inválida 8 dígitos 9.

enfáticamente le animo a utilizar las funciones previstas por la biblioteca de socket incluida en su sistema operativo o entorno de compilación.

Editar: (Aunque estaba implícito, pero) por supuesto, también puede tener cuadrantes hexadecimales, a la 192.168.1.0x0A para 192.168.1.10, y por supuesto puede mezclar y combinar su contenido sádico con mayúsculas y minúsculas , a la 0xC0.0xa8.1.010 para 192.168.1.8. Pruebe algunos ejemplos usando ping si quiere divertirse. Esto funciona muy bien multiplataforma (probado hace un tiempo mientras juraba bajo Linux, NetBSD y Win32.)

hacer otras modificaciones en respuesta a la solicitud de KaluSingh Gabbar: Por ejemplo, puede especificar 192.168.1.10 como 0xc0a8010a y todavía representa un número IP válida, al estilo de:

[[email protected] ~]$ ping 0xc0a8010a 
PING 0xc0a8010a (192.168.1.10) 56(84) bytes of data. 
^C 
--- 0xc0a8010a ping statistics --- 
3 packets transmitted, 0 received, 100% packet loss, time 2479ms 
+3

Sabía que había trampas, pero acaba de abrir una nueva lata de gusanos. :) –

+0

Heh. Me enteré por el camino difícil. El RFC describe esto en detalle minutiae, pero nada es mejor que un administrador molesto demoging un producto en el sitio del cliente diciéndole que "las direcciones IP con 8 o 9 en ellos no funcionan en los controles de nuestra dirección IP de la aplicación!"La caza de un problema inexistente fue divertido ... –

+1

Corolario: Nunca asuma que todas las personas usan espacios para alinear perfectamente las cosas Algunos ceros uso * suspiro * –

29

La solución que me decidí por fue:

bool Config::validateIpAddress(const string &ipAddress) 
{ 
    struct sockaddr_in sa; 
    int result = inet_pton(AF_INET, ipAddress.c_str(), &(sa.sin_addr)); 
    return result != 0; 
} 

Esto funciona para la mayoría de los casos que se mencionaron en otras respuestas. No reconoce las direcciones IP con formato hexadecimal o octal, pero eso es aceptable para mi aplicación.

+3

¿Y esto se votó porque ...? Definitivamente es una respuesta aceptable para el OP. :) –

+0

¿Es compatible con IPv6? No creas que sí ... – aberaud

+0

@Wagaf Eso no estaba en los requisitos. Actualicé la pregunta. –

38

Boost.Asio proporciona la clase ip::address. Si lo que desea es para verificar la cadena, se puede utilizar de esta manera:

std::string ipAddress = "127.0.0.1"; 
boost::system::error_code ec; 
boost::asio::ip::address::from_string(ipAddress, ec); 
if (ec) 
    std::cerr << ec.message() << std::endl; 

Esto también funciona para hexadecimales y octales quads. Esta es también una solución mucho más portátil.

+1

+1 para la portabilidad y funciona para hexagonales/octavales. La mejor respuesta del lote. –

+1

@tothphu: Usted debe informar de este tema para impulsar, lo más probable es un descuido. –

2

He hecho lo mismo solo con C stdlib funciones aunque no es compatible con los cuádriceps octales como se mencionó anteriormente, pero eso no debería ser un problema, puedo agregar fácilmente esa parte y dársela. Al ser un principiante (estudiante), ni siquiera sabía hasta ahora que es posible obtener un número octal dentro de su ip. Pensé que debe ser un decimal.

+1

No te sientas mal del todo. Estuve felizmente inconsciente de muchos de los detalles mencionados aquí antes de hacer esta pregunta, incluidos los números octales que mencionó. –

0
vector<string> &split(const string &s, char delim, vector<string> &elems) { 
    stringstream ss(s); 
    string item; 
    while(getline(ss, item, delim)) { 
     elems.push_back(item); 
    } 
    return elems; 
} 

vector<string> split(const string &s, char delim) { 
    vector<string> elems; 
    return split(s, delim, elems); 
} 


bool isIPAddress(string ipaddr){ 

    if (ipaddr.length()){ 
      vector<string> _ip=split(ipaddr,'.'); 
      if (_ip.size()==4){ 
        for (int i=0; i < 4; i++){ 
          for (int j=0; j < _ip[i].length(); j++) 
            if (!isdigit(_ip[i][j])) return false; 
          if ((atoi(_ip[i].c_str()) < 0) || (atoi(_ip[i].c_str()) > 255)) return false; 
        } 
      return true; 
      } 
    } 
    return false; 
} 
2

Aquí está el programa C para validar una dirección IPV4 determinada. He supuesto que la dirección IP está en formato decimal. Por favor, dame tu opinión sobre esto.

// strTokenFunction.cpp : Check if the specified address is a valid numeric IP address. 
    // This function is equavalent to the IPAddress.TryParse() method in C# 

#include "stdafx.h" 
#include <stdio.h> 
#include <conio.h> 
#include <string.h> 

bool isValidIpAddress(char *st) 
{ 
    int num, i, len; 
    char *ch; 

    //counting number of quads present in a given IP address 
    int quadsCnt=0; 

    printf("Split IP: \"%s\"\n", st); 

    len = strlen(st); 

    // Check if the string is valid 
    if(len<7 || len>15) 
     return false; 

    ch = strtok(st, "."); 

    while (ch != NULL) 
    { 
     quadsCnt++; 
     printf("Quald %d is %s\n", quadsCnt, ch); 

     num = 0; 
     i = 0; 

     // Get the current token and convert to an integer value 
     while(ch[i]!='\0') 
     { 
      num = num*10; 
      num = num+(ch[i]-'0'); 
      i++; 
     } 

     if(num<0 || num>255) 
     { 
      printf("Not a valid ip\n"); 
      return false; 
     } 

     if((quadsCnt == 1 && num == 0) || (quadsCnt == 4 && num == 0)) 
     { 
      printf("Not a valid ip, quad: %d AND/OR quad:%d is zero\n", quadsCnt, quadsCnt); 
      return false; 
     } 

     ch = strtok(NULL, "."); 
    } 

    // Check the address string, should be n.n.n.n format 
    if(quadsCnt!=4) 
    { 
     return false; 
    } 

    // Looks like a valid IP address 
    return true; 
} 

int main() 
{ 
    char st[] = "192.255.20.30"; 
    //char st[] = "255.255.255.255"; 
    //char st[] = "0.255.255.0"; 

    if(isValidIpAddress(st)) 
    { 
     printf("The given IP is a valid IP address\n"); 
    } 
    else 
    { 
     printf("The given IP is not a valid IP address\n"); 
    } 
} 
5

Si se encuentra en ventanas se puede hacer uso de WSAStringToAddress y con base en el valor de retorno es sabido, si el argumento pasado es IP o no válida. Esto es compatible con IPv4 & IPv6 desde Windows 2000 en adelante.

+4

un ejemplo sería útil – johannes

1

algunas correcciones menores para fijar algunos casos como 127..0.1, 127.0.0 .. y quitar espacios si tienen:




    #include <iostream> 
    #include <vector> 
    #include <string> 
    #include <sstream> 
    #include <algorithm> 
    #include <iterator> 
    #include <stdio.h> 

    using namespace std; 

    vector split(char* str, char delimiter) 
    { 
     const string data(str); 
     vector elements; 
     string element; 
     for(int i = 0; i 0) {//resolve problem: 127.0..1 
        elements.push_back(element); 
        element.clear(); 
       } 
      } 
      else if (data[i] != ' ') 
      { 
       element += data[i]; 
      } 

     } 
     if (element.length() > 0)//resolve problem: 127.0..1 
      elements.push_back(element); 
     return elements; 
    } 

    bool toInt(const string& str, int* result) 
    { 
     if (str.find_first_not_of("") != string::npos) 
      return false; 

     stringstream stream(str); 
     stream >> *result; // Should probably check the return value here 
     return true; 
    } 

    /** ipResult: the good ip address, e.g. spaces are removed */ 
    bool validate(char* ip, string *ipResult) 
    { 
     const static char delimiter = '.'; 
     const vector parts = split(ip, delimiter); 
     *ipResult = ""; 
     if (parts.size() != 4) 
      return NULL; 

     for(int i = 0; i 255) 
       return NULL; 

      if (i == 3) { 
       *ipResult += parts[i]; 
      } else { 
       *ipResult += (parts[i] +"."); 
      } 

     } 
     return true; 
    } 

    int main() 
    { 
     string ip; 
     printf("right %d\n", validate("127.0.0.1", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("wrong %d\n", validate("127.0.0.-1", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("wrong %d\n", validate("127..0.1", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("wrong %d\n", validate("...0.1", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("wrong %d\n", validate("127.0.0.", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("right %d\n", validate("192.168.170.99", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("right %d\n", validate("127.0 .0 .1", &ip)); 
     printf("good ip: %s\n", ip.c_str()); 
     printf("\n"); 

     system("pause"); 

     return 0; 
    } 

No
Cuestiones relacionadas