打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ip有效性检测及代码优化

  说明:最近编写代码时,需要用C语言实现设置ip地址的功能,奈何本人所涉及的能力有限,通过网上查阅,找到了一个可以使用的程序代码,其中,有个检查ip地址是否有效的函数,但该函数却存在着一些不安全性,恰同时我刚好需要该函数,因此,我对该函数进行了一些优化,在此,想分享一下自己在优化该程序过程中的一些想法和思路。借此,希望能够和各位前辈进行交流。其中,原代码编写者的博客地址是:https://blog.csdn.net/lihuibo128/article/details/43668065  。

  如果该代码还存在着不足,希望各位前辈能够批评指正。

一、源程序函数

包含的头文件:

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<string.h>#include<regex.h>

 源程序:

/*函数返回值:    0    :成功    -1    :失败*/int check_right_ip(const char *ip){        int status = 0;    int cflags = REG_EXTENDED;    regmatch_t pmatch[1];    const size_t nmatch = 1;    regex_t reg;    char str_ip[30] = "";    const char *pattern = "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}";//存在局限        strcpy(str_ip, ip);    regcomp(&reg, pattern, cflags);    status = regexec(&reg,str_ip,nmatch,pmatch,0);    if(status==REG_NOMATCH)    {            printf("No match\n");        return -1;    }    else if(status == 0)    {        return 0;        }    regfree(&reg);     return 0;}

  说明:在源程序中,所使用的是利用正则表达式来进行数据位的有效检测,关于正则表达式函数的的用法,由于本篇主要侧重点在于代码的优化,在此,并不多详细讲解。可以参考网上其他博主的相关介绍。该程序的测试主程序如下:

int main(){    char *ip = "192.168.1.12";    int res = 0;        res = check_right_ip(ip);    if (res == -1)    {        fprintf(stdout, "the format of ip is wrong...\r\n");        return -1;    }    fprintf(stdout, "the format of ip is right\r\n");        return 0;}

 运行结果:

  通过运行结果,可以看到,该程序运行正常。

二、程序的优化之数据有效性的检测

  通过上述的简单测试,可以看到,该程序可以正常运行,但却存在着一些潜在的bug。首先,我们都知道,IP的有效格式是:"192.168.1.12",但比如有一天有人想输入的ip地址是:“192.168.1.12.12”,那么该程序的的运行结果是怎么的呢,如下是测试的主程序:

int main(){    char *ip = "192.168.1.12.12";    int res = 0;        res = check_right_ip(ip);    if (res == -1)    {        fprintf(stdout, "the format of ip is wrong...\r\n");        return -1;    }    fprintf(stdout, "the format of ip is right\r\n");        return 0;}

编译运行之后的结果如下:

  通过结果发现,该程序竟然运行正确,但这是我们想要的结果吗?结果是否定的,因此,我们需要考虑如果避免这种情况,通过对比两个ip地址我们可以发现,其中的点"."的个数是不一样的,因此,我们可以来计算该点的个数来判断一下ip地址的有效性。修改之后的check_right_ip()的函数如下:

/*函数返回值:    0    :成功    -1    :失败*/int check_right_ip(const char *ip){        int status = 0;    int cflags = REG_EXTENDED;    regmatch_t pmatch[1];    const size_t nmatch = 1;    regex_t reg;    char str_ip[30] = "";    const char *pattern = "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}";//存在局限        /**************new add **********************/    char *pNext = NULL;    char *pTmp = NULL;    int count = 0;        strcpy(str_ip, ip);    regcomp(&reg, pattern, cflags);    status = regexec(&reg, str_ip, nmatch, pmatch, 0);     if(status == REG_NOMATCH)    {        printf("No match\n");        return -1;    }    regfree(&reg);       pNext = (char *)ip;
   while (1)
   {
      pTmp = strchr(pNext, '.');
      if (pTmp == NULL)
      {
         if (count != 3)
         {
            return -1;
         }
         if (count == 3)
         {
            break;
         }
      }
      count ;
      pNext = pTmp 1;
 }
 
  return 0;}

  说明:在该函数中,我们增加了两个了指针,来进行数据位的有效计算“.”的个数,然后根据“.”的个数来判断其是否有效。下面是修改之后程序的运行结果

  此时,可以看出,该程序的的运行结果与我们预期的结果一致,但这就结果这个问题了吗??考虑这么一种情况,假如有人小手一抖,只是在ip地址中,多增加了一个“.”,并没有在其后面添加数字,那么此时运行结果如下呢?下面我们来测试一下。主程序的代码如下:

int main(){    char *ip = "192.168.1.12.";    int res = 0;        fprintf(stdout, "ip = %s\r\n", ip);    res = check_right_ip(ip);    if (res == -1)    {        fprintf(stdout, "the format of ip is wrong...\r\n");        return -1;    }    fprintf(stdout, "the format of ip is right\r\n");        return 0;}

运行结果如下:

  额,该程序能够运行出正确的结果。但本人在测试时,且发现,有时候并不能正确运行出结果,当时提示的错误信息是,段错误。通过排查发现,是 check_right_ip()中的pNext = pTmp 1;这句话导致的,原因如下,当指针pTmp指向其最后一个"."时,pNexr = pTmp 1;会指向其末尾, 再此使用strchr()函数时,就会导致段错误。此时,有两种方法解决,一种就是在 pNext = pTmp 1; 之后,判断pNext是否等于‘\0’,另一种则是让pNext 最初指向 str_ip,而不是指向ip,因为str_ip数组中,末尾全部为'\0',使用strchr()时,不会导致指向不该指向的地址。

修改之后的check_right_ip()的函数如下:

/*函数返回值:    0    :成功    -1    :失败*/int check_right_ip(const char *ip){        int status = 0;    int cflags = REG_EXTENDED;    regmatch_t pmatch[1];    const size_t nmatch = 1;    regex_t reg;    char str_ip[30] = "";    const char *pattern = "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}";//存在局限        /**************new add **********************/    char *pNext = NULL;    char *pTmp = NULL;    int count = 0;        strcpy(str_ip, ip);    regcomp(&reg, pattern, cflags);    status = regexec(&reg, str_ip, nmatch, pmatch, 0);     if(status == REG_NOMATCH)    {        printf("No match\n");        return -1;    }    regfree(&reg);        /**************new add **********************/    pNext = (char *)ip;    while (1)    {        pTmp = strchr(pNext, '.');        if (pTmp == NULL)        {            if (count != 3)            {                return -1;            }            if (count == 3)            {                break;            }        }        count  ;        pNext = pTmp   1;                if (*pNext == '\0')        {            return -1;                        }    }         return 0;}

  此时,我们就将其格式讨论完了,但是,假如我们输入的ip地址是:"192.168.278.12"时呢?从实际情况上出发,该字符串是不符合ip地址规范的,我们来具体的测试一下:

主程序源码:

int main(){    char *ip = "192.168.1.278";    int res = 0;        fprintf(stdout, "ip = %s\r\n", ip);    res = check_right_ip(ip);    if (res == -1)    {        fprintf(stdout, "the format of ip is wrong...\r\n");        return -1;    }    fprintf(stdout, "the format of ip is right\r\n");        return 0;}

运行结果:

 

  我们发现,其结果与我们想的不同,想来原因也是,我们使用正则表达式来进行判断时,并没有对其进行数字大小的判断,因此,我们需要对其数据的有效性进行判断,修改之后的源码如下:

check_right_ip源码:

int check_right_ip(const char *ip){        int status = 0;    int cflags = REG_EXTENDED;    regmatch_t pmatch[1];    const size_t nmatch = 1;    regex_t reg;    char str_ip[30] = "";    const char *pattern = "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}";//存在局限        /**************new add **********************/    char *pNext = NULL;    char *pTmp = NULL;    int count = 0;    char tmpBuf[4] = {0};            strcpy(str_ip, ip);    regcomp(&reg, pattern, cflags);    status = regexec(&reg, str_ip, nmatch, pmatch, 0);     if(status == REG_NOMATCH)    {        printf("No match\n");        return -1;    }    regfree(&reg);        /**************new add **********************/    pNext = (char *)ip;    while (1)    {        pTmp = strchr(pNext, '.');        if (pTmp == NULL)        {            if (count != 3)            {                return -1;            }            if (count == 3)            {                break;            }        }        count  ;        pNext = pTmp   1;                if (*pNext == '\0')        {            return -1;                        }    }        pNext = (char *)str_ip;    while (count--)    {        pTmp = strchr(pNext, '.');        if((pTmp - pNext) == 3)        {            strncpy(tmpBuf, pNext, 3);            if (atoi(tmpBuf) > 255)            {                return -1;            }            memset(tmpBuf, 0, sizeof(tmpBuf));        }                pNext = pTmp   1;            }         return 0;}

运行结果:

  此时,运行结果与想象宏的结果一致。。

 

来源:http://www.icode9.com/content-4-82151.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Linux C 支持正则表达式的字符串替换函数
C++:实现split分割字符串
qt 学习笔记(转载)
嵌入式开发小记,实用小知识分享
C语言sprintf与sscanf函数[总结]
aoti函数的实现
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服