• C语言 IPv6 十六进制 转 十进制


      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <math.h>
      4 
      5 //ipv4地址转换
      6 int ipv4_to_i(const char *ip, unsigned int *ipv4_addr)
      7 {
      8     char str_ip_index[4] = {''};
      9     unsigned int ip_int, ip_add = 0;
     10     unsigned int j = 0, a = 3, i = 0;
     11 
     12     for(i = 0; i <= strlen(ip); i++) {
     13         if (ip[i] == '' || ip[i] == '.') {
     14             ip_int = atoi(str_ip_index);
     15             if (ip_int > 255)
     16                 return 0;
     17 
     18             ip_add += (ip_int * pow(256, a));
     19             a--;
     20             memset(str_ip_index, 0, sizeof(str_ip_index));
     21 
     22             j = 0;
     23             continue;
     24         }
     25 
     26         str_ip_index[j] = ip[i];
     27         j++;
     28     }
     29 
     30     *ipv4_addr = ip_add;
     31 
     32     return 1;
     33 }
     34 
     35 /* ipv6 无符号整型数组转化为字符串 */
     36 void ipv6_to_str(char *addr_str, unsigned int ipv6_addr[])
     37 {
     38         /* ipv6地址128位,数组ip维数默认为4 */
     39         /* 输出格式为: A:B:C:D:E:F:G:H. */
     40         int i;
     41         unsigned short msw, lsw;
     42         char *addr_str_end_ptr;
     43 
     44         addr_str[0] = '';
     45         addr_str_end_ptr = addr_str;
     46         for (i = 0; i < 4; i++)
     47         {
     48                 msw = ipv6_addr[i] >> 16;
     49                 lsw = ipv6_addr[i] & 0x0000ffff;
     50                 addr_str_end_ptr += sprintf(addr_str_end_ptr, "%X:%X:", msw, lsw); 
     51         }
     52         *(addr_str_end_ptr - 1) = '';
     53 }
     54  
     55 char * string_white_space_trim(char *str)
     56 {
     57         /* 移除字符串中空格 */
     58         int index;
     59         int new_index;
     60         int str_length;
     61 
     62         str_length = strlen(str);
     63 
     64         for (index = 0, new_index = 0; index < str_length; index++)
     65         {
     66                 if (!isspace((unsigned char)str[index]))
     67                 {
     68                         str[new_index] = str[index];
     69                         new_index++;
     70                 }
     71         }
     72 
     73         str[new_index] = '';
     74 
     75         return str;
     76 }
     77  
     78 int string_char_count(const char *string, char character)
     79 {
     80         /* 计算字符串中,给定字符的数量 */
     81         int i;
     82         int str_length;
     83         int count = 0;
     84 
     85         str_length = strlen(string);
     86         for (i = 0; i < str_length; i++)
     87                 if (string[i] == character)
     88                         count++;
     89 
     90         return count;
     91 }
     92  
     93 int ipv6_address_field_type_get(const char * field_str)
     94 {
     95         /* 判断ipv6地址域类型                           */
     96         int i = 0;
     97         int length;
     98         int type;
     99         unsigned int ipv4_addr;
    100 
    101         /* 通过长度判断          */
    102         /* 16进制数字域: 1-4    */
    103         /* "::"域:0             */
    104         /* ipv4地址域: 7-15     */
    105 
    106         length = strlen(field_str);
    107 
    108         if (0 == length)
    109         {
    110                 type = 1;
    111         }
    112         else if (length <= 4)
    113         {
    114                 // 确保每个数字为16进制
    115                 for (i = 0; i < length; i++)
    116                         if (!isxdigit((unsigned char)field_str[i]))
    117                                 return -1;
    118                 type = 0;
    119         }
    120         else if((length >= 7) && (length <= 15))
    121         {
    122                 //确保是有效的ipv4地址
    123                 if (ipv4_to_i(field_str, &ipv4_addr))
    124                         type = 2;
    125                 else
    126                         type = -1;
    127         }
    128         else
    129         {
    130                 type = -1;
    131         }
    132 
    133         return type;
    134 }
    135  
    136 int ipv6_to_i(const char *addr_str, int length, unsigned int ipv6_addr_ptr[])
    137 {
    138         /***************************************************************************/
    139         /* 功能:解析ipv6地址字符串,转换为无符号整形,存入4个无符号整形的一维数组  */
    140         /* ipv6地址 128位,prefix length:                                          */
    141         /*                         - 64 for EUI-64 addresses                       */
    142         /*                         - 128 for non-EUI-64 addresses                  */
    143         /* 输入:ipv6地址字符串,地址位数,默认为128位                             */
    144         /* 输出:返回解析成功或失败;指向4个无符号整形的一维数组的指针              */
    145         /****************************************************************************/
    146 
    147         char addr_str_copy[256];
    148         int i, num_fields;
    149         //unsigned int *ret_addr_ptr;
    150         unsigned short int addr_field_arr[8];
    151         int addr_index;
    152         char *ith_field; // 指向地址当前域
    153         int  ith_field_type; // 地址域类型
    154         char *next_field;
    155         int  double_colon_field_index = -1; // 字符串地址中"::"的位置
    156         unsigned int ipv4_address; // ipv6地址中的ipv4部分
    157         unsigned int msw, lsw;
    158         int error = 0;
    159 
    160         //复制一份,以便操作
    161         strcpy(addr_str_copy, addr_str);
    162 
    163         // 移除字符串中的空格字符
    164         string_white_space_trim(addr_str_copy);
    165 
    166         /* IPv6地址可能几种格式:                                          */
    167         /* 1) 2006:DB8:2A0:2F3B:34:E35:45:1   用16进制表示每个域的值(16位) */
    168         /* 2) 2006:DB8::E34:1 , "::" 代表0,且只能出现一次       */
    169         /* 3) 2002:9D36:1:2:0:5EFE:192.168.12.9 带有ipv4地址     */
    170 
    171         // 计算字符串中冒号,字符串中地址域数比冒号多一个
    172         num_fields = string_char_count(addr_str_copy, ':') + 1;
    173 
    174         // 域最大数量为length/16 + 2
    175         // 如  ::0:0:0:0:0:0:0:0.
    176         if (num_fields > ((length >> 4) + 2))
    177         {
    178                 ipv6_addr_ptr = NULL;
    179                 return 0;
    180         }
    181 
    182         // 初始化
    183         ith_field = addr_str_copy;
    184 
    185         for (i = 0, addr_index = 0; i < num_fields; i++)
    186         {
    187                 // 获得下一个域的指针
    188                 next_field = strchr(ith_field, ':');
    189 
    190                 /* 若当前是最后一个域, next_field 是 NULL                       */
    191                 /* 否则,替换':'为'', 字符串可以结束,从而ith_field指向当前域   */
    192                 /* next_field指向下一个域头部                                    */
    193                 if (NULL != next_field)
    194                 {
    195                         *next_field = '';
    196                         ++next_field;
    197                 }
    198 
    199                 // 发现这个域的类型
    200                 ith_field_type = ipv6_address_field_type_get(ith_field);
    201 
    202                 switch (ith_field_type)
    203                 {
    204                         case 0:
    205                         // 域类型为16进制表示
    206 
    207                                 if (addr_index >= (length >> 4))
    208                                 {
    209                                         error = 1;
    210                                         break;
    211                                 }
    212                                 // 字符串转换为16进制
    213                                 addr_field_arr[addr_index] = (unsigned short)strtoul(ith_field, NULL, 16);
    214                                 ++addr_index;
    215                         break;
    216 
    217                         case 1:
    218                         // 域类型为 "::"
    219 
    220                                 // 若出现在字符串的开头或结尾,忽略
    221                                 if ((0 == i) || (i == num_fields - 1))
    222                                 {
    223                                         break;
    224                                 }
    225 
    226                                 // 若出现大于一次,错误
    227                                 if (double_colon_field_index != -1)
    228                                 {
    229                                         error = 1;
    230                                         break;
    231                                 }
    232 
    233                                 // 记下位置
    234                                 double_colon_field_index = addr_index;
    235 
    236                         break;
    237 
    238                         case 2:
    239                         // 域类型为ipv4地址
    240 
    241                                 // 确保在地址中还有两个未设置的域
    242                                 if (addr_index >= 7)
    243                                 {
    244                                         error = 1;
    245                                         break;
    246                                 }
    247 
    248                                 // ipv4地址解析
    249                                 ipv4_to_i(ith_field, &ipv4_address);
    250 
    251                                 // 存储高16位
    252                                 addr_field_arr[addr_index] = (unsigned short)(ipv4_address >> 16);
    253 
    254                                 // 存储低16位
    255                                 addr_field_arr[addr_index + 1] = (unsigned short)(ipv4_address & 0x0000ffff);
    256 
    257                                 addr_index += 2;
    258 
    259                         break;
    260                         default:
    261                                 error = 1;
    262                         break;
    263                 }
    264 
    265                 if (error)
    266                 {
    267                         ipv6_addr_ptr = NULL;
    268                         return 0;
    269                 }
    270 
    271                 ith_field = next_field;
    272         }
    273 
    274         // 计算的域不是8,并且没有"::",错误
    275         if ((addr_index != (length >> 4)) && (-1 == double_colon_field_index))
    276         {
    277                 ipv6_addr_ptr = NULL;
    278                 return 0;
    279         }
    280 
    281         if ((addr_index != (length >> 4)) && (-1 != double_colon_field_index))
    282         {
    283                 // 设置相应"::"对应addr_field_arr中位置为0
    284                 memmove(addr_field_arr + (double_colon_field_index + (length >> 4) - addr_index),
    285                                         addr_field_arr + double_colon_field_index, (addr_index - double_colon_field_index) * 2);
    286                 memset(addr_field_arr + double_colon_field_index, 0, ((length >> 4) - addr_index) * 2);
    287         }
    288 
    289         for (i = 0; i < 4; i++)
    290         {
    291                 msw = addr_field_arr[2 * i];
    292                 lsw = addr_field_arr[2 * i + 1];
    293 
    294                 (ipv6_addr_ptr)[i] = (msw << 16 | lsw);
    295         }
    296 
    297         return 1;
    298 }
    299  
    300 int main(void)
    301 {
    302         char addr[256] = {"0"};
    303         unsigned int ip_v4 = 3356567252;
    304         unsigned int ipv6[4] = {3356567252, 3356567253, 3356567254, 3356567255};
    305         unsigned int ipv61[4] = {65538, 196612, 327686, 458760};
    306 
    307         char *ipv6_str1 = "1:2:3:4:5:6:7:8";
    308         char *ipv6_str2 = "1:2:3:4:5:6:7:8::";
    309         char *ipv6_str3 = "::1:2:3:4:5:6:7:8";
    310         char *ipv6_str4 = "1:2:3:4:5:6:192.168.1.100";
    311         char *ipv6_str5 = "1:2::5:6:7:8";
    312         char *ipv6_str6 = "1::3:4:5:6:7:8";
    313         char *ipv6_str7 = "1::4:5:6:7:8";
    314         char *ipv6_str8 = "1::8";
    315  
    316         unsigned int ipv6_addr[4];
    317         unsigned int ipv4_addr;
    318         unsigned int ipv6_addr_sum = 1;
    319         int flag;
    320         int i;
    321  
    322         ipv6_to_str(addr, ipv61);
    323         printf("ipv6: %s
    ", addr);
    324  
    325         flag = ipv4_to_i("192.168.1.100", &ipv4_addr);
    326         if (flag)
    327         {
    328                 printf("ipv4_addr: %u
    ", ipv4_addr);
    329         }
    330  
    331         flag = ipv6_to_i(ipv6_str1, 128, ipv6_addr);
    332         if (flag)
    333         {
    334                 for (i = 0; i < 4; i++)
    335                 {
    336                         printf("ipv6_addr: %u
    ", ipv6_addr[i]);
    337                         ipv6_addr_sum += ipv6_addr[i];
    338                 }
    339 
    340                 printf("ipv6_addr_sum: %u
    ", ipv6_addr_sum);
    341         }
    342  
    343         return 0;
    344 }

    编译运行:

    [root@node1 ~]# gcc ddd.c -lm
    [root@node1 ~]# ./a.out
    ipv6: 1:2:3:4:5:6:7:8
    ipv4_addr: 3232235876
    ipv6_addr: 65538
    ipv6_addr: 196612
    ipv6_addr: 327686
    ipv6_addr: 458760
    ipv6_addr_sum: 1048597

  • 相关阅读:
    NHibernate开源框架Cuyahoga学习之数据访问实现
    Petshop4.0 缓存设计学习
    Jquery实现ToolTip之元素定位
    客户单操作Cookie
    .Net 通过MySQLDriverCS操作MySQL
    NHibernate的基本使用
    提高ASP.NET性能的十大方法
    工作流引擎下基于表达式Tree复杂验证的实现
    C#注册表操作
    WinForm应用程序中的ComboBox实现ReadOnly功能
  • 原文地址:https://www.cnblogs.com/wangjq19920210/p/10395458.html
Copyright © 2020-2023  润新知