html ip测试源码,ip有效性检测及代码优化

标签:

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

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

一、源程序函数

包含的头文件:

#include

#include

#include

#include

#include

#include

源程序:

/*

函数返回值:

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;

}

运行结果:

8258aa44fb2768ac7267b5fb39f78cce.png

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

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

通过上述的简单测试,可以看到,该程序可以正常运行,但却存在着一些潜在的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;

}

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

0ce95a0e9a142742c79f2785e61f120b.png

通过结果发现,该程序竟然运行正确,但这是我们想要的结果吗?结果是否定的,因此,我们需要考虑如果避免这种情况,通过对比两个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;

}

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

562ab728ec9a3f622a97124d32b00182.png

此时,可以看出,该程序的的运行结果与我们预期的结果一致,但这就结果这个问题了吗??考虑这么一种情况,假如有人小手一抖,只是在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;

}

运行结果如下:

e5810e3fb1a781c90c84961521bacbe4.png

额,该程序能够运行出正确的结果。但本人在测试时,且发现,有时候并不能正确运行出结果,当时提示的错误信息是,段错误。通过排查发现,是 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;

}

运行结果:

6af56b3ca64b02ac693eb829089afd02.png

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

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;

}

运行结果:

d06b89ae2080903fd38f7947262c7afa.png

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

标签:

来源: https://www.cnblogs.com/gykai/p/9976990.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值