确定字符串是否是C中的有效IPv4地址

什么是确定字符串是否包含IPv4地址的好方法? 我应该使用isdigit()吗?

我问过类似的C ++问题 。 你应该能够使用我当时提出的稍微修改过的(对于C)版本。

 bool isValidIpAddress(char *ipAddress) { struct sockaddr_in sa; int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr)); return result != 0; } 

你需要#include 来使用inet_pton()函数。

根据对问题的评论进行更新:如果您想知道C风格的字符串是否包含 IP地址,那么您应该结合到目前为止给出的两个答案。 使用正则表达式查找与IP地址大致匹配的模式,然后使用上面的函数检查匹配项以查看它是否真实。

这是我前一段时间写的一个例程,用于在网络上生成各种可疑模式的嵌入式系统。 因此,它绝对使用像网络库甚至标准C库这样的花哨的东西,更喜欢避开所有现代的东西,如字符串标记和(颤抖)正则表达式库:-)为此,它适合于几乎你可以找到自己的任何环境,它的速度非常快。

虽然,如果你所处的环境有类似checkIp4Addess()东西,我建议你改用它。 这表明你在做嵌入式工作时有时需要忍受的东西(尽管这一个真正的解决方案)。

 int isValidIp4 (char *str) { int segs = 0; /* Segment count. */ int chcnt = 0; /* Character count within segment. */ int accum = 0; /* Accumulator for segment. */ /* Catch NULL pointer. */ if (str == NULL) return 0; /* Process every character in string. */ while (*str != '\0') { /* Segment changeover. */ if (*str == '.') { /* Must have some digits in segment. */ if (chcnt == 0) return 0; /* Limit number of segments. */ if (++segs == 4) return 0; /* Reset segment values and restart loop. */ chcnt = accum = 0; str++; continue; } 

  /* Check numeric. */ if ((*str < '0') || (*str > '9')) return 0; /* Accumulate and check segment. */ if ((accum = accum * 10 + *str - '0') > 255) return 0; /* Advance other segment specific stuff and continue loop. */ chcnt++; str++; } /* Check enough segments and enough characters in last segment. */ if (segs != 3) return 0; if (chcnt == 0) return 0; /* Address okay. */ return 1; } 

我会使用这个正则表达式(由正则表达式示例提供 ):

 `\b(?:\d{1,3}\.){3}\d{1,3}\b` 

我会给出“不要两个问题”的解决方案:

 #include  int isIp_v4( char* ip){ int num; int flag = 1; int counter=0; char* p = strtok(ip,"."); while (p && flag ){ num = atoi(p); if (num>=0 && num<=255 && (counter++<4)){ flag=1; p=strtok(NULL,"."); } else{ flag=0; break; } } return flag && (counter==3); } 

编辑:strtok可能不是线程安全的(信任Adam Rosenfield)

这是我尝试使用非常低级别的C编程(实际上在我的一个PIC单片机程序中使用)。 它不使用string.h库。 它不使用指针,因为我使用的这个编译器不适合它们,无论如何你可以使用它们。 考虑到这一点,并且通常会定义一个变量来处理传入的数据缓冲区,如下所示:

 #define isdigit(x) isamong(x,"0123456789") char IPACK_Buff[IPACK_SIZE]; // Check if string is a valid IP int IPACK_is_valid_ip(int len) { int i = 0; int j = 0; int NumDots = 0; char number[4] = "000\0"; // Check first char is numeric if (!isdigit(IPACK_Buff[0])) return 0; for (i = 0 ; i< len; i++) { if (isdigit(IPACK_Buff[i])) { number[j] = IPACK_Buff[i]; j++; if (j>3) return 0; } else if (IPACK_Buff[i] == '.') { if (atof(number)> 255) return 0; memset(number, '\0', 4); j = 0; NumDots++; if(NumDots>3) return 0; } } if (NumDots == 3) { return 1; } else return 0; }// 

我希望这个function可以帮助你们。 同样,在批评之前考虑这个function的低级别。

 int validateIP4Dotted(const char *s) { int len = strlen(s); if (len < 7 || len > 15) return 0; char tail[16]; tail[0] = 0; unsigned int d[4]; int c = sscanf(s, "%3u.%3u.%3u.%3u%s", &d[0], &d[1], &d[2], &d[3], tail); if (c != 4 || tail[0]) return 0; for (int i = 0; i < 4; i++) if (d[i] > 255) return 0; return 1; } 

在url / uri rfc 3986中,Augmented Backus-Naur Form(ABNF)ipv4地址定义为:

  IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet dec-octet = DIGIT ; 0-9 / %x31-39 DIGIT ; 10-99 / "1" 2DIGIT ; 100-199 / "2" %x30-34 DIGIT ; 200-249 / "25" %x30-35 ; 250-255 

我用以下格式用regexp实现了检查:

 // Although the RFC says ipv6 octects like 001 are not valid, it would be risky // not to accept those #define decoct "([01]?[0-9]?[0-9]|2[0-4][0-0]|25[0-5])" #define ipv4 "(" decoct "\\." decoct "\\." decoct "\\." decoct ")" 

我需要弄清楚传入的字符串是否“包含”一个有效的IP地址,并返回一个指向传入字符串的有效IP地址部分的指针,如果是这样的话。 如果不是,则返回空指针。

这里的代码似乎有效,虽然尚未经过良好测试,但我只是编写并快速尝试。 我没有添加支票来限制数字到一个字节的值,但请检查以确保它们限制为三位数。

 int IsDigit(char ch) { int is_digit = 0; if ( ch >= '0' && ch <= '9' ) { is_digit = 1; } return is_digit; } #define FIND_IP_START 0 #define FIND_IP_DIGIT 1 #define FIND_IP_DIG_OR_DEC 2 #define FIND_IP_DECIMAL 3 #define FIND_IP_DIG_OR_END 4 #define FIND_IP_END 5 #define FIND_IP_DONE 6 char * StringContainsValidIpAddress(char * input_buf_pointer) { char * pos = input_buf_pointer; int octets = 0; int digits = 0; int state = FIND_IP_START; char * ip_string = 0; char ch = *pos; while ( (ch != NULL) && (state != FIND_IP_DONE) ) { switch ( state ) { case FIND_IP_START: if ( IsDigit(ch) ) { ip_string = pos; //potential start of ip string digits = 1; // first digit octets = 1; // of first octet state = FIND_IP_DIG_OR_DEC; } break; case FIND_IP_DIGIT: if ( IsDigit(ch) ) { digits = 1; // first digit octets++; // of next octet if ( octets == 4 ) { state = FIND_IP_DIG_OR_END; } else { state = FIND_IP_DIG_OR_DEC; } } else { // Start over state = FIND_IP_START; } break; case FIND_IP_DIG_OR_DEC: // Here we are looking for another digit // of the same octet or the decimal between // octets. if (ch == '.') { state = FIND_IP_DIGIT; } else if ( IsDigit(ch) ) { digits++; // next digit if ( digits == 3 ) { state = FIND_IP_DECIMAL; } } else { // Start over state = FIND_IP_START; } break; case FIND_IP_DECIMAL: if (ch == '.') { state = FIND_IP_DIGIT; } break; case FIND_IP_DIG_OR_END: // Here we are looking for another digit // of the same octet or the end (which could // be a space or CR or LF or really any // non-digit). if ( IsDigit(ch) ) { digits++; // next digit if ( digits == 3 ) { state = FIND_IP_END; } } else { *pos = 0; // Null terminate the IP address string state = FIND_IP_DONE; } break; case FIND_IP_END: if ( !IsDigit(ch) ) { *pos = 0; // Null terminate the IP address string state = FIND_IP_DONE; } break; case FIND_IP_DONE: break; default: break; } // Fetch the next character ch = *++pos; } if (state == FIND_IP_DONE) { return ip_string; } else { return 0; } } 

像这样从头开始做。 此代码包含用于检查字符串是否包含IPv4 IP地址的工具。

 #define MAX_HEX_NUMBER_COUNT 8 int ishexdigit(char ch) { if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F')) return(1); return(0); } int IsIp6str(char *str) { int hdcount=0; int hncount=0; int err=0; int packed=0; if(*str==':') { str++; if(*str!=':') return(0); else { packed=1; hncount=1; str++; if(*str==0) return(1); } } if(ishexdigit(*str)==0) { return(0); } hdcount=1; hncount=1; str++; while(err==0&&*str!=0) { if(*str==':') { str++; if(*str==':') { if(packed==1) err=1; else { str++; if(ishexdigit(*str)||*str==0&&hncount='0'&&*str<='9') { value=*str-'0'; str++; } else return(0); nnumber=1; while(err==0&&*str!=0) { if(*str>='0'&&*str<='9') { if(255/value>=10) { value*=10; if(255-value>=(*str-'0')) { value+=(*str-'0'); str++; } else err=1; } else err=1; } else { if(*str=='.') { str++; if(*str>='0'&&*str<='9') { if(nnumber==4) err=1; else { if(*str=='0') { *str++; if(*str!='.'&&*str!=0) err=1; else { nnumber++; value=0; } } else { nnumber++; value=*str-'0'; str++; } } } else { err=1; } } else if(*str!=0) err=1; } } if(nnumber!=4) err=1; return(err==0); } 

函数IsIp4str(char * str)测试字符串是否包含IP地址版本四地址格式。 IsIp6str(char * str)函数测试,如果字符串包含IP地址版本六地址格式。

函数IsIp4str(char * str)和IsIp6str(char * str)如果string str包含IP地址则返回true,如果string str不包含IP地址则返回false。

如果你需要检查字符串是否包含IP地址IPv6格式,它可以完成int IsIp6str(char * str)函数。 它的工作方式与此相同

这是我一直在努力的function的开始,虽然不完整,它可能会引发想法或评论。 function背后的思想是;

  1. 检查传递的char指针或字符串是没有端口的IPv4地址,使用其最小/最大大小,字符串中有多少个点,以及冒号:字符是否存在。
  2. 如果字符串不是带有或没有端口的IPv4,那么检查字符串是否是IPv6,如果不是IPv6,则检查IP格式是否未被识别,因为它尚未实现。

我认为这取决于你想要深入研究问题的深度,你想要了解可能发生什么问题的深度。

 #include  #include  #include  #include  #include  int isIP(char *ip) { char *data_ptr = ip; // Create a pointer to passed data int orig_str_size = 0; // Create an int to hold passed data size int str_index = 0; // Create an int to iterate individual ip characters int dot_count = 0; // Create an int to check for the number of dots // Count the number of characters in data_ptr while (*data_ptr++ != '\0'){ orig_str_size++; } if(orig_str_size <= 0) // If nothing { printf("Get a grip, ip is empty\n\n"); exit(0); } else // If within IPv4 size range if(orig_str_size >= 7 && orig_str_size <= INET_ADDRSTRLEN) { char *data1_ptr = ip; // Create a pointer to passed data printf("Within IPv4 range, %i characters in length\n\n", orig_str_size); // Count the number of dots in the string, 3 for IPv4 for(str_index; str_index < orig_str_size; str_index++) { if(data1_ptr[str_index] == '.'){ dot_count++; } } // If theres 3 dots, while ignoring dots, check each char is a digit if(dot_count == 3) { printf("There's three dots in the string\n\n"); data1_ptr = ip; str_index = 0; // Iterate the string char by char for(str_index; str_index < orig_str_size; str_index++) { // Ignoring dots if(data1_ptr[str_index] != '.') { // If isdigit() is happy its a digit and isalpha() happy not alphabetic if(isdigit(data1_ptr[str_index]) && !isalpha(data1_ptr[str_index])) { printf("Digit found and is not alphabetic\n\n"); continue; } else if(!isdigit(data1_ptr[str_index]) && isalpha(data1_ptr[str_index])) { printf("Not a recognised IPv4 address, character detected in string\n\n"); exit(0); } } } return 0; } } else // If IPv6 if(orig_str_size > 0 && orig_str_size > INET_ADDRSTRLEN && orig_str_size <= INET6_ADDRSTRLEN) { printf("Within IPv6 range %i\n\n", orig_str_size); return 0; } else { printf("Unknown target format, the format you provided as a target is not implemented\n\n"); exit(0); } } 

TCP / IP网络互联

RFC791 - 互联网协议 - https://tools.ietf.org/html/rfc791

CISCO网络互联手册http://docwiki.cisco.com/wiki/Internetworking_Technology_Handbook

开放系统互连参考模型http://docwiki.cisco.com/wiki/Internetworking_Basics#Open_Systems_Interconnection_Reference_Model

CISCO TCP / IP网络故障排除https://www.cisco.com/en/US/docs/internetworking/troubleshooting/guide/tr1907.pdf

IPv4允许的最大TCP / IP网络端口号是多少?

 // you can even use the v value array to return the unsigned int // version of the IP if desired in an unsigned int reference. bool isvalidip(const char * s) { char t[8]; int p = 0; int v[8]; int numnum = 0; for (int i = 0; i < (int) strlen(s); i++) { char c = s[i]; int cgood = 0; if (c >= '0' && c <= '9' && p < 4) { t[p++] = c; t[p] = 0; cgood++; continue; } if (p == 4) return false; if (c == '.') { if (!p) return false; v[numnum++] = atoi(t); p = 0; cgood++; continue; } if (!cgood) return false; // not a valid character if (numnum > 4) return false; // we have a lot of dots.... } v[numnum++] = atoi(t); // we did not have a dot, we had a NULL..... if (numnum != 4) return false; // we must have had 4 valid numbers.... for (int i = 0; i < 4; i++) { if (v[i] < 0 || v[i] > 255) return false; // octet values out-of-range } return true; //we good.. } 

我认为下面的C代码片段应该可行

 bool validate_ip4(const char* buffer) { if (NULL == buffer) return false; register const char* pos = buffer; register unsigned char ch = *pos; register unsigned short count = 0; while (ch != NULL) { if (!((ch >= '0' && ch <= '9') || ch == '.')) return false; if (ch == '.') if (++count > 3) return false; ch = *++pos; } if (count == 3 && *--pos != '.') return true; return false; } 

inet_addr()比用于数字和点符号表示IPv4 IP地址检查的inet_aton()要好得多。