我是靠谱客的博主 大气康乃馨,最近开发中收集的这篇文章主要介绍IPv6子网数量计算器IPv6子网计算器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

IPv6子网计算器

最近需要做一个IPv6子网计算器,网上有个前端工具网站倒是可以实现,但是不知道什么原理,自己要用C语言实现一个工具,所以没办法就去研究了一个星期。。。最终倒是成功了,具体测试也通过了,不过代码还是不太完善的,这边就分享一下实现代码。希望能给需要的人一个思路。
本程序可以根据需要分成的子网个数或者要分成的IPv6前缀两种方式来划分

/*
**********************************************************************
*                        CREATE BY BCTECH                            *
**********************************************************************
*                   * @Author: Gu
*                   * @Date:   2021-06-04 08:41:51
*                   * @Last Modified by:   Gu
*                   * @Last Modified time: 2021-06-07 21:31:24
**********************************************************************
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <arpa/inet.h>
#include <string.h>
//网络字节序
/**
 * [ip_to_str description]
 * @Author      gu
 * @DateTime    2021-06-04T08:43:20+0800
 * @Description 整型数IP转成字符串
 * @param       str                      [description]
 * @param       ip                       [description]
 * @return                               [description]
 */
int ip_to_str(char *str, unsigned int *ip) {
    int domain;
    unsigned int ipv6add[4];
    if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0) {
        domain = AF_INET;
        ipv6add[0] = ip[3];
        ipv6add[1] = 0;
        ipv6add[2] = 0;
        ipv6add[3] = 0;
    } else {
        domain = AF_INET6;
        ipv6add[0] = ip[0];
        ipv6add[1] = ip[1];
        ipv6add[2] = ip[2];
        ipv6add[3] = ip[3];
    }
    if (inet_ntop(domain, ipv6add, str, INET6_ADDRSTRLEN) == NULL) {
        return -1;
    }
    return 0;
}
//网络字节序
/**
 * [str_to_ip description]
 * @Author      gu
 * @DateTime    2021-06-04T08:43:49+0800
 * @Description IP地址转成整型数
 * @param       str                      [description]
 * @param       ip                       [description]
 * @return                               [description]
 */
int str_to_ip(char *str, unsigned int *ip) {
    int Afamily;
    ip[0] = 0;
    ip[1] = 0;
    ip[2] = 0;
    ip[3] = 0;
    if (strstr(str, ":") != NULL) {
        Afamily = AF_INET6;
    } else {
        Afamily = AF_INET;
    }
    if (inet_pton(Afamily, str, ip) <= 0) {
        return -1;
    } else {
        // ntohl(ip);//网络字节序转主机字节序
    }
    return 0;
}

//gcc -Wall -o subnet_calculat subnet_calculat.c -lm
int main(int argc, char const *argv[]) {
    char *ipstr = argv[1];//IP地址
    int changenum = 0;//用来求划分后的前缀
    int prefix = atoi(argv[2]);//IP子网
    int need_prefix = 0;//划分后的子网前缀
    int movenum = 0, runmove = 0;//二进制移动值
    unsigned int tmpvalue = 0;//公用临时变量
    unsigned int tmpvalue2 = 0;
    unsigned int tmpvalue3 = 0;
    unsigned int tmpvalue4 = 0;
    long long int run = 0;//遍历子网个数变量
    long long int runtime = 0;//子网个数
    unsigned int ip[4] = {0};
    int res = -1;
    char iptemp[64];
    unsigned int need_ip[4] = {0};//IP中转变量
    if (strstr(argv[3], "/")) {//按子网前缀划分
        changenum = atoi(argv[3] + 1) - prefix;
        if (changenum < 0) {
            printf("error select prefix should be more than ip_prefix!n");
            return 1;
        }
    } else {//按需要的子网个数划分
        int testnum = atoi(argv[3]); //要划分的个数/划分的子网
        double lognum = (log10(testnum) / log10(2));
        if (floor(lognum + 0.5) == (lognum)) {//取整
            changenum = round(lognum); //取划分的子网数跟2的对数
        } else {
            changenum = round(lognum + 0.5); //取划分的子网数跟2的对数
        }
    }
    need_prefix = prefix + changenum;
    res = str_to_ip(ipstr, ip);
    if (res < 0) {
        printf("str_to_ip error!n");
        return 0;
    }

    runtime = pow(2, changenum);
    if (runtime <= 0) {
        runtime = 1;
    }
    for (run = 0; run < runtime ; run++) {
        need_ip[0] = ip[0];
        need_ip[1] = ip[1];
        need_ip[2] = ip[2];
        need_ip[3] = ip[3];
        if (need_prefix <= 32) {//结果子网小于等于32,操作整型IP地址的第一位
            tmpvalue = htonl(need_ip[0]);//主机字节序转网络字节序
            movenum = 32 + changenum - need_prefix;
            if (movenum < 0) {
                printf("error no more subnet!n");
                return 0;
            }
            tmpvalue2 = (((tmpvalue >> (movenum)) << changenum)  | run) << (movenum - changenum);
            need_ip[0] = ntohl(tmpvalue2);
        } else if (need_prefix <= 64) {//结果子网小于等于64大于32,操作整型IP地址的第一和二位
            movenum = 64 - need_prefix;
            if (movenum < 0) {
                printf("error no more subnet!n");
                return 0;
            }
            runmove =  need_prefix - 64;
            tmpvalue = htonl(need_ip[0]);
            tmpvalue2 = (tmpvalue | (run >> runmove));
            need_ip[0] = ntohl(tmpvalue2);
            tmpvalue3 = htonl(need_ip[1]);
            tmpvalue4 = (((tmpvalue3 >> (movenum - 1)) + run) << movenum);
            need_ip[1] = (ntohl(tmpvalue4));
        } else if (need_prefix <= 96) {//结果子网小于等于96大于64,操作整型IP地址的第一和三位
            movenum = 96 - need_prefix;
            if (movenum < 0) {
                printf("error no more subnet!n");
                return 0;
            }
            runmove =  need_prefix - 96;
            tmpvalue = htonl(need_ip[1]);
            tmpvalue2 = (tmpvalue | (run >> runmove));
            need_ip[1] = ntohl(tmpvalue2);
            tmpvalue3 = htonl(need_ip[2]);
            tmpvalue4 = (((tmpvalue3 >> (movenum - 1)) + run) << movenum);
            need_ip[2] = (ntohl(tmpvalue4));//网络字节序转主机字节序
        } else {//结果子网大于96,操作整型IP地址的第一和四位
            movenum = 128 - need_prefix;
            if (movenum < 0) {
                printf("error no more subnet!n");
                return 0;
            } else {
                tmpvalue2 = (((tmpvalue >> (movenum - 1)) + run) << movenum);
            }
            runmove =  need_prefix - 128;
            tmpvalue = htonl(need_ip[2]);
            tmpvalue2 = (tmpvalue | (run >> runmove));
            need_ip[2] = ntohl(tmpvalue2);
            tmpvalue3 = htonl(need_ip[3]);
            tmpvalue4 = (((tmpvalue3 >> (movenum - 1)) + run) << movenum);
            need_ip[3] = (ntohl(tmpvalue4));
        }
        memset(iptemp, 0, sizeof(iptemp));
        res = ip_to_str(iptemp, need_ip);
        if (res < 0) {
            printf("ip_to_str error!n");
            return 0;
        }
    }
    return 0;
}

我自己的基本测试是没什么问题的,有的问题就是当子网的地址数或者子网数过多超过double最大值时,会有问题,所以如果使用尽量不要计算过大的子网。(其实我也是一知半解,所以不太好描述为什么这样写,反正代码他就是能用了哈哈哈哈哈哈哈哈)等我真的搞懂了我就再解释下吧。哈哈哈!

最后

以上就是大气康乃馨为你收集整理的IPv6子网数量计算器IPv6子网计算器的全部内容,希望文章能够帮你解决IPv6子网数量计算器IPv6子网计算器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部