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;
}

运行结果:

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

原文地址:https://www.cnblogs.com/gykai/p/9976990.html

时间: 2024-10-14 04:38:46

ip有效性检测及代码优化的相关文章

代理ip最新识别方法及代理ip有效性检测方法

网络营销时代,网络成为企业营销的重要工具.线上有非常多的营销渠道可以利用.当然方法也就越来越多:自媒体.抖音.电商.微商等等,尤其当走进大数据时代,爬虫可以帮助企业在线上采集到相当精准的用户信息,成为企业制定营销策略的关键.当然,技术流的推广人员都知道,爬虫运行少不了代理ip的辅助. 代理ip最新识别方法以及代理ip有效性检测方法 一.代理ip常见的一些功能 1.突破自身ip访问限制,现在有许多的网站都对ip地址访问进行了限制,这时则可以通过代理ip来突破限制,让自己进入网站. 2.提高访问速度

链路的有效性检测

链路的有效性检测 当网络发生单通.连接被防火墙Hang住.长时间GC或者通信线程发生非预期异常时,会导致链路不可用且不易被及时发现. 特别是异常发生在凌晨业务低谷期间,当早晨业务高峰期到来时,由于链路不可用会导致瞬间的大批量业务失败或者超时, 这将对系统的可靠性产生重大的威胁. 从技术层面看,要解决链路的可靠性问题,必须周期性的对链路进行有效性检测.目前最流行和通用的做法就是心跳检测. 心跳检测机制分为三个层面: 1) TCP层面的心跳检测,即TCP的Keep-Alive机制,它的作用域是整个T

java代理ip有效检测

java实现代理ip有效检测,依赖Apache的HttpClient 正式版:       /** * 批量代理IP有效检测 * * @param proxyIpMap * @param reqUrl */ public static void checkProxyIp(Map<String, Integer> proxyIpMap, String reqUrl) { for (String proxyHost : proxyIpMap.keySet()) { Integer proxyPor

python爬虫之反爬虫(随机user-agent,获取代理ip,检测代理ip可用性)

python爬虫之反爬虫(随机user-agent,获取代理ip,检测代理ip可用性) 目录 随机User-Agent 获取代理ip 检测代理ip可用性 随机User-Agent fake_useragent库,伪装请求头 from fake_useragent import UserAgent ua = UserAgent() # ie浏览器的user agent print(ua.ie) # opera浏览器 print(ua.opera) # chrome浏览器 print(ua.chro

CENTOS 7 内网网段在用IP地址检测Shell脚本优化版

脚本内容 #!/bin/bash ############################################################################# # 用途:网段IP地址检测 # 作者:Dylan # 日期:2019年10月31日 11:56 ############################################################################# #############################

对代理IP进行检测是否可用

第一种方法是使用telnetlib import telnetlib import requests from lxml import etree #解析此url页面的IP url = 'http://ip.geiwoxiao.com/' headers = { 'User-Agent':'User-Agent:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;' } #使用requests请求指定页面,返回html页面

java正则表达式小练习(IP地址检测、排序,叠词的处理,邮件地址的获取)

import java.util.Arrays; import java.util.Comparator; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; class MyComparator implements Comparator<String>{ public int compare(String ip1, String ip2) { Pattern p

部落冲突云手机多开改不同IP防检测挂机

现在很多手游工作室采用云手机多开这个技术挂机一个可以赚金的手游,云手机相当于一个虚拟手机的存在.云手机顾名思义是与云技术有关,但我不想讲的那么高深,大家可以百度一下阿里云,腾讯云等服务器了解一下,云手机就是云服务器下的虚拟框架手机.(安卓系统)可以叫它云手机,也可以叫它云平板.它不是手游模拟器,也不是真实手机.下面,小编我以<部落冲突>为例进行代练的操作示范 首先,安装部落冲突手游,以360版本为例,在360手游市场中搜索并安装<部落冲突>.这时,您可以启动并运行<部落冲突&

ip速度检测与云主机|VPS的抉择:bandwagonhost digitalocean hostWind Vultr Linode

最近的梯子断了,网站又被注销了.又到了挑vps的时间了.其实, 这些东西,烦死人了.挺浪费生命的. 首先速度测试, MTR测试 网站速度测试 17CE. http://tool.chinaz.com/speedtest/ https://tools.ipip.net/traceroute.php  站长网提供的工具:这个相信大部分博主与草根站长都会用. 更多的,推荐参考一下:https://www.zhihu.com/question/21454090/answer/206535929 VPS,