udhcp源码详解(五) 之DHCP包--options字段

NXP(恩智浦)—TJA1043TK CAN收发器芯片详解 本文章主要讲解NXP(恩智浦)—TJA1043TK CAN收发器的相关知识。 阅读详情

   udhcp源码详解(五)             之DHCP包--options字段

Author : hui <632254504@qq.com>

From : <http://blog.youkuaiyun.com/hui_love2046>

Created : 2010-10-25

 

       中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说,理论上说从IP地址池取到一个空闲的IP,就这么一句,在源码的体现也是一大段。算啦,讲多少算多少吧,进入主题!

            struct dhcpMessage报文里uint8_t options[308]字段,在整个DHCP过程中是报文的一个很重要的字段,博文的系列(二)有讲解该字段的数据组织方式,CLV(Code + Len + Value),现在来讲解下怎么把选项信息添加进该字段,以及怎么从该字段取到相应的选项信息。

            options字段存储三类数据:

            a).  DHCP_PADDING           填充字节, 没有任何意义,填充 0x00

            b).  DHCP_END                   potions字段结束的标志              0xFF

            c).  选项信息<CLV>          对于DHCP过程真正有价值的信息,承载了选项数据(V)

 

对于选options字段的操作主要就是read/write value:

1、根据选项信息的CODE从option字段取出选项信息.

 

[cpp] view plain copy

  1. /*  
  2.  * 参数struct dhcpMessage *packet DHCP报文  
  3.  * int code需要获得什么选项信息(选项信息的标识) 
  4.  * 
  5.  * 返回指向选项信息的指针(去除了 OPT_CODE,OPT_LEN) 
  6.  * 未找到返回NULL 
  7.  */  
  8. uint8_t *get_option(struct dhcpMessage *packet, int code)  
  9. {  
  10.     int i, length;  
  11.     uint8_t *optionptr;  
  12.     int over = 0, done = 0, curr = OPTION_FIELD;  
  13.   
  14.     optionptr = packet->options;  
  15.     i = 0;  
  16.     length = 308;   /* 整个options字段的长度308 */  
  17.   
  18.     /* 在options字段里查找code选项标识信息*/  
  19.     while (!done) {  
  20.         if (i >= length) {   /* 查找完所有字段都未找到code标识的信息,返回NULL */  
  21.             LOG(LOG_WARNING, "bogus packet, option fields too long.");  
  22.             return NULL;  
  23.         }  
  24.   
  25.         //CLV方式存储数据  
  26.         //这里与struct option_set的data存储相似  
  27.         //OPT_CODE字节上存储code标识  
  28.         //OPT_LEN 字节上存储信息长度  
  29.         //OPT_LEN后就是存储信息  
  30.   
  31.         if (optionptr[i + OPT_CODE] == code) {  //Found  
  32.             if (i + 1 + optionptr[i + OPT_LEN] >= length) {  //检查选项信息长度  
  33.                 LOG(LOG_WARNING, "bogus packet, option fields too long.");  
  34.                 return NULL;  
  35.             }  
  36.             return optionptr + i + 2;   //Found,返回选项信息的首地址  
  37.         }  
  38.           
  39.         switch (optionptr[i + OPT_CODE]) {  
  40.         case DHCP_PADDING:  //DHCP_PADING(填充)字节,直接 i++;  
  41.             i++;  
  42.             break;  
  43.         case DHCP_OPTION_OVER:  //选项过载DHCP_OPTION_OVER  
  44.             if (i + 1 + optionptr[i + OPT_LEN] >= length) {  
  45.                 LOG(LOG_WARNING, "bogus packet, option fields too long.");  
  46.                 return NULL;  
  47.             }  
  48.   
  49.             /* 
  50.                 optionptr[i + OPT_CODE] == DHCP_OPTION_OVER选项过载; 
  51.                 optionptr[i + 3]存放了采用哪个字段来存储过载的选项 
  52.                 可能存储过载选项的字段: 
  53.                     uint8_t sname[64]; //server host name (ASCIZ)  
  54.                     uint8_t file[128];  // boot file name (ASCIZ)  
  55.  
  56.                 over = optionptr[i + 3];记录下使用那个字段存储过载选项 
  57.             */  
  58.   
  59.   
  60.             /* 
  61.              * 
  62.             The code for this option is 52, and its length is 1.  Legal values 
  63.             for this option are: 
  64.              
  65.                     Value   Meaning 
  66.                     -----   -------- 
  67.                       1     the 'file' field is used to hold options 
  68.                       2     the 'sname' field is used to hold options 
  69.                       3     both fields are used to hold options 
  70.              
  71.              Code   Len  Value 
  72.             +-----+-----+-----+ 
  73.             |  52 |  1  |1/2/3| 
  74.             +-----+-----+-----+ 
  75.             */  
  76.   
  77.             over = optionptr[i + OPT_DATA];  
  78.             i += optionptr[i + OPT_LEN] + 2;  
  79.               
  80.         //  over = optionptr[i + 3];      /* Error */  
  81.         //  i += optionptr[OPT_LEN] + 2;  /* Error */  
  82.             break;  
  83.         case DHCP_END:  //选项字段结束标志 DHCP_END 0xff  
  84.   
  85.             /*  
  86.              * 当选项过载的时候(curr == OPTION_FILE允许选项过载) 
  87.              *  首先用file字段,不够的话再用sname字段 
  88.              *  使用file字段的时候: 
  89.              *      over的右起的第0位必须为1 
  90.              *  使用sname字段: 
  91.              *      over的右起的第一位必须为1 
  92.              */  
  93.             if (curr == OPTION_FIELD && over & FILE_FIELD) {  
  94.                 optionptr = packet->file;  
  95.                 i = 0;  
  96.                 length = 128;  
  97.                 curr = FILE_FIELD;  
  98.             } else if (curr == FILE_FIELD && over & SNAME_FIELD) {  
  99.                 optionptr = packet->sname;  
  100.                 i = 0;  
  101.                 length = 64;  
  102.                 curr = SNAME_FIELD;  
  103.   
  104.                         //没有或不允许选项过载或over(options[i + 3])标志不允许,结束查找返回NULL  
  105.             } else done = 1;  
  106.             break;  
  107.   
  108.   
  109.         /* 
  110.          * 不是填充信息:DHCP_PADDING 
  111.          * 选项过载:DHCP_OPTION_OVER 
  112.          * 选项结束:DHCP_END 
  113.          * 
  114.          * 表明是属于选项信息,所以可以直接改变偏移量: 
  115.          * i += option[OPT_LEN + i] + 2; 
  116.          */  
  117.         default:  
  118.             i += optionptr[OPT_LEN + i] + 2;  
  119.         }  
  120.     }  
  121.     return NULL;  
  122. }  

 

在源码busybox 1.2的udhcp源码中,对于从options字段取出选项信息,在对选项过载的处理是存在错误的,

 

 

[cpp] view plain copy

  1. case DHCP_OPTION_OVER:  //选项过载DHCP_OPTION_OVER  
  2.     if (i + 1 + optionptr[i + OPT_LEN] >= length) {  
  3.         LOG(LOG_WARNING, "bogus packet, option fields too long.");  
  4.         return NULL;  
  5.     }  
  6.         /*           
  7.      * Code Len  Value 
  8.      * +-----+-----+-----+ 
  9.      * |  52 |  1  |1/2/3| 
  10.      * +-----+-----+-----+ 
  11.      */  
  12.     over = optionptr[i + OPT_DATA];  
  13.     i += optionptr[i + OPT_LEN] + 2;  
  14.           
  15. //  over = optionptr[i + 3];       /* 未改动源码 */  
  16. //  i += optionptr[OPT_LEN] + 2;   /* 未改动源码 */  
  17.     break;  

 

  2、向options字段写入选项信息

         a).  写入是添加在options字段中最后的选项后面,即DHCP_END标志之前

               查找DHCP_END标志字段:

 

[cpp] view plain copy

  1. /* return the position of the 'end' option (no bounds checking) */  
  2. int end_option(uint8_t *optionptr)  
  3. {  
  4.     int i = 0;  
  5.   
  6.     /* 在选项字段里找到DHCP_END的偏移 */  
  7.     /* 在选项字段里面里三类信息: 
  8.         1.DHCP_PADDING 填充字节 
  9.         2.DHCP_END  选项结束字节 
  10.         3.选项信息<CLV> code + length + value 
  11.         */  
  12.     while (optionptr[i] != DHCP_END) {  
  13.         if (optionptr[i] == DHCP_PADDING) i++;  //填充字节DHCP_PADDING  
  14.         else i += optionptr[i + OPT_LEN] + 2;   //选项信息  
  15.     }  
  16.     return i;  
  17. }  

        b).   选项信息已经在一个字符串里以CLV方式组织好,直接copy到DHCP_END标志位置,DHCP_END向后移动:

 

[cpp] view plain copy

  1. /* add an option string to the options (an option string contains an option code, 
  2.  * length, then data) */  
  3. int add_option_string(uint8_t *optionptr, uint8_t *string)  
  4. {  
  5.     int end = end_option(optionptr);//找到DHCP_END在选项字段里偏移  
  6.   
  7.     /* end position + string length + option code/length + end option */  
  8.         //检查需要添加的选项信息后的长度是否大于选项字段的最大长度  
  9.     if (end + string[OPT_LEN] + 2 + 1 >= 308) {  
  10.         LOG(LOG_ERR,"Option 0x%02x did not fit into packet!",string[OPT_CODE]);  
  11.         return 0;  
  12.     }  
  13.     DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]);  
  14.     memcpy(optionptr + end, string, string[OPT_LEN] + 2);  
  15.     optionptr[end + string[OPT_LEN] + 2] = DHCP_END;//在<CLV>的最后添加上DHCP_END  
  16.     return string[OPT_LEN] + 2; //返回<CLV>长度  
  17. }  

        c).  把选项信息按CLV的方式组织好存放到一个字符串里,最后调用add_option_string把在字符串内组织好的选项信息添加进options字段:

 

[cpp] view plain copy

  1. /* add a one to four byte option to a packet */  
  2. /* add_simple_option函数只能想选项字段添加OPT_LEN = 4 bytes的选项 */  
  3. /*  optionptr: 报文选项字段的首地址 
  4.     code:   选项code 
  5.     data:   选项value 
  6.  
  7.     返回值是 <CLV>的长度 
  8.     返回0 表示添加失败 
  9.     */  
  10. int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data)  
  11. {  
  12.     struct dhcp_option *dh;  
  13.   
  14.     /* 检查需要添加的选项是否符合标准的选项 */  
  15.     /* 在dhcp_options数组里查找 */  
  16.     for (dh=dhcp_options; dh->code; dh++) {  
  17.         if (dh->code == code) {      //Found  
  18.             uint8_t option[6], len;  
  19.   
  20.             option[OPT_CODE] = code;    //添加code  
  21.             len = option_lengths[dh->flags & TYPE_MASK];//计算length  
  22.             option[OPT_LEN] = len;      //添加length  
  23.   
  24.                         /*  
  25.                          * 假设data长度是一个字节,但在大端字节序的机器里 
  26.                              * 但存放在uint32_t里的放在最高地址的地方, 
  27.                              * 所以data << 8 * (4 - len) 把她移到低位 
  28.                              */  
  29.             if (BB_BIG_ENDIAN) data <<= 8 * (4 - len);  
  30.   
  31.             /* This memcpy is for broken processors which can't 
  32.              * handle a simple unaligned 32-bit assignment */  
  33.             memcpy(&option[OPT_DATA], &data, 4);  
  34.             return add_option_string(optionptr, option);  
  35.         }  
  36.     }  
  37.   
  38.     DEBUG(LOG_ERR, "Could not add option 0x%02x", code);  
  39.     return 0;  
  40. }  

save_snippets.pnguploading.4e448015.gif转存失败重新上传取消save_snippets.pnguploading.4e448015.gif转存失败重新上传取消

11、RK3566/3568 Android11切割屏幕 长条屏 显示 在使用 RK3566 平台进行 Android 11 开发时,遇到切割屏(长条屏)显示画面不全。本文将详细介绍如何配置,以及如何修改 HWComposer 来调整显示区域,解决图像缩放问题。我这边屏幕是lvds接口的,分辨率1920 1080实际的屏物理尺寸是1920x463。 阅读详情

相关推荐

ESP32-CAM与TFT屏幕实时图像传输:Arduino环境下的OV2640驱动实践

本文详细介绍了在Arduino环境下实现ESP32-CAM与TFT屏幕实时图像传输的完整实践方案。重点解析了OV2640摄像头的驱动配置、硬件引脚连接、TFT屏幕初始化及图像显示优化技巧,帮助开发者快速构建稳定的实时图像显示系统,适用于物联网监控、门禁系统等场景。

cuda7parallel的博客 115

DHCP option

DHCP

°Destiny 1万+

Dirsearch的下载、安装和使用(全)

Dirsearch工具的下载、安装和使用,超详细超全面

weixin_68416970的博客 1万+

DHCP Option字段

Tag Name Data Length Meaning Reference 0 Pad 0 None [RFC2132] 1 Subnet Mask 4 Subnet Mask Value [RFC2132] 2 Time Offset 4 Time Offset in Seconds from UTC (note: dep...

weixin_33725272的博客 5130

【ArcGIS教程】基于DEM数据的洪水淹没分析——提取淹没区并计算淹没区洪水量

使用ArcGIS开展洪水淹没区分析、提取淹没区并计算淹没区洪水量的详细说明,如果想获取教程中实验数据,请关注微信公众号【GIS小能手】然后在后台留言。

weixin_45469245的博客 6820

RK3568嵌入式Linux多屏显示开发指南

摘要:本篇RK3568嵌入式Linux多屏显示开发指南详细介绍了基于Qt应用层的实现方案。文章首先概述了技术架构,说明从Qt应用到硬件显示的完整流程。然后提供了两种实现方案:推荐使用Qt内置多屏支持方案,包含完整的C++代码示例和配置文件说明;对于需要精细控制的场景,给出了基于libdrm API的底层实现方案。最后重点讨论了屏幕旋转处理和多屏协同工作模式的关键技术要点,包括扩展桌面、镜像模式等实现方法。

froxy的专栏 1572

DHCP OPTION字段收集

code length congent 0 0 填充字段 1 4 子网掩码 2 4 时间偏移 3 4*N Route Add1;Route Add2;Route AddN; 4 5 6 4*N DNS Server1;DNS Server2;DNS ServerN 7 4*N LOG Server1;Log Server2;Log ServerN 15

471

MediaCodec视频解码流程详解及参考demo

本文主要讲解mediacodec的视频解码流程,及demo参考例子。

分享音视频技术 7875

android 4.0.3上 增加option60选项功能总结

1、setting里面按dhcp获取ip 会调用到/system/core/libnetutils下dhcp_utils.c文件        dhcp_utils.c是负责和dhcpcd守护进程通信的。 2、dhcpcd守护进程是在init.rc里面启动的。相关代码在external/dhcpcd/dhcpcd.c文件里面 3、dhcp_utils.c 里面有个dhcp_do_reques

zvivi521的专栏 3190

第三节:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入门 - 对接后端登录接口(上)

这里是Vben Admin V5版本实战体验,上一节我们前端已正常运行,但是没有实现登录。本节的重点是对接后端接口。上一节地址:第一节:Vben Admin 最新 v5.0初体验第二节:Vben Admin 登录逻辑梳理和对接后端准备后端我们采用Python的Flask项目,Flask-SQLAlchemy管理数据库模型,Flask-Migrate进行模型迁移。参考版本如下:Flask3.0.23.1.1到这里,登录接口完成,下一步要实现获取用户信息和权限的接口功能。

cuiwin的专栏 1861

图解联合概率密度、边缘概率密度、条件概率密度之间的关系

简要图解联合概率密度、边缘概率密度、条件概率密度之间的关系

一个搬运知识的笨小孩 2万+

【网络协议详解】——DHCP技术(学习笔记)

动态主机配置协议DHCP(Dynamic Host Configuration Protocol)是一种用于集中对用户IP地址进行动态管理和配置的技术。即使规模较小的网络,通过DHCP也可以使后续增加网络设备变得简单快捷。DHCP协议由RFC 2131定义,采用客户端/服务器通信模式,由客户端(DHCP Client)向服务器(DHCP Server)提出配置申请,服务器返回为客户端分配的配置信息。DHCP可以提供两种地址分配机制,网络管理员可以根据网络需求为不同的主机选择不同的分配策略。

2201_75633021的博客 1603

整车的智能配电系统

本文探讨了汽车电网安全的重要性,分析了传统汽车电网的现状,并重点介绍了半导体在汽车智能配电系统中的作用。半导体凭借其单向导电性和可控性,如二极管、MOSFET等,提供了更高效、安全的电力控制。通过对比传统保险丝与半导体器件,阐述了半导体在过流保护、电压监测和故障诊断方面的优势,强调其在减少安全隐患、提高能源管理和续航里程方面的贡献。极氪智能配电系统展示了如何运用半导体技术实现整车能源的精细化管理,降低维修成本,减少线束复杂性,提升安全性能。

让你爱上电路设计 1612

udhcp源码详解(五) 之DHCP包--options字段

中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说,理论上说从IP地址池取到一个空闲的IP,就这么一句,在源码的体现也是一大段。算啦,讲多少算多少吧,进入主题! struct dhcpMessage报文里uint8_t op...

weixin_33778544的博客 328

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

udhcp源码详解(五)

<br />udhcp源码详解(四)             之DHCP包--options字段<br />Author : hui <632254504@qq.com><br />From : <http://blog.youkuaiyun.com/hui_love2046><br />Created : 2010-10-25<br /> <br />           中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就

前进路上的点滴 5182

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

udhcp源码详解(二)

<br />udhcp源码详解(二)             之定义的结构体<br />Author : hui <632254504@qq.com><br />From : <http://blog.youkuaiyun.com/hui_love2046><br />Created : 2010-10-2     ---   2010-10-3<br /> <br />定义的数据结构对于C程序的重要性,不言而喻。面向对象设计的程序是一个个对象的集合,而面向过程语言设计的程序则是数据结构与算法的集合。<br />下面来

前进路上的点滴 8082

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

udhcp源码详解(二)之定义的结构体

udhcp源码详解(二)之定义的结构体 Author : hui<632254504@qq.com> From :<http://blog.youkuaiyun.com/hui_love2046> Created : 2010-10-2---2010-10-3 定义的数据结构对于C程序的重要性,不言而喻。面向对象设计的程序是一...

echo 888

udhcp源码详解(六)--script

首先得讲明udhcp客户端设置IP的机制。 在udhcp中,客户端通过和主机的多次报文交互协商而获得可用的IP地址。在获得IP地址之后,客户端使用execle函数调用shell脚本完成客户端ip,netmak,dns,gateway等等参数的设定。而shell脚本的调用在script.h和script.c中实现。 以下为script.c源码中的主要实现函数: /* Fill dest wit

baidu20008的专栏 2993

udhcp源码详解(二)--转

定义的数据结构对于C程序的重要性,不言而喻。面向对象设计的程序是一个个对象的集合,而面向过程语言设计的程序则是数据结构与算法的集合。 下面来分析的是dhcp server中的定义结构体: 1)、在packet.h文件里定义了DHCP报文的格式: struct dhcpMessage报文的字段虽然都有注释,但还是有必要讲下options字段。 options在大多文档中的说法是可选字...

weixin_33674976的博客 190

udhcpd源码分析4--获取client报文及发包动作

1:重要的结构体   获取的报文是UDP的payload部分,结构体struct dhcpMessage描述了dhcp报文的结构。 /* packet.h */ struct dhcpMessage { u_int8_t op; /* 1 for client,2 for server */ u_int8_t htype; /...

weixin_30563917的博客 312

DHCP 技术详解:动态主机配置协议的原理、应用与配置实践

DHCP 采用客户端/服务器(Client/Server)模式,通过 DHCP 服务器为网络中的客户端动态分配 IP 地址、子网掩码、默认网关、DNS 服务器地址等配置信息。相比手动配置静态地址,DHCP 的动态分配机制显著降低了管理负担,尤其在设备频繁变更的网络环境中表现出色。Option 82:由中继或 Snooping 设备添加,包含 Circuit ID(接口信息)和 Remote ID(设备标识)。Option 184:用于语音网络,携带网络呼叫处理器地址等信息。

zero_number的博客 1398

DHCP字段含义

分享DHCP option( option 82 、 option 60 、option 43) DHCP option 82 、 option 60 、option 43dhcp报文中的一个选项,该选项在dhcp报文中为可变长的字段,option选项中包含了部分租约信息、报文类型等。option选项中最多可以包括255个option,最少为1个option。 一、option 82 1、

xianweijian的博客 2万+

DHCP 协议报文详解 | 字段含义 | 抓包分析

……

u013669912的博客 4212

android 4.0 系统设置dhcp获取ip增加option60 选项

搜索了很多资料,介绍都是修改/system/core/libnetutils下面的代码 dhcp 获取ip过程; 1、先由客户端发送discover消息,这个消息属于广播,网内的dhcp都会收到这个消息,一般在这个消息内增加option60选项 2、服务器如果能够提供给客户端一个ip地址,则会给客户端发送一个offer消息,里面包含提供的ip消息 3、客户端一般按照谁最先给提供ip,就给那

zvivi521的专栏 5659

DHCP option 120开发

当DHCP服务器无法确定客户端的MAC地址时,它会将offer报文设置为广播。这通常发生在DHCP服务器和客户端之间没有直接的网络连接时,例如在跨越不同子网的情况下。需要注意的是,DHCP的offer报文只有在第一次分配IP地址时才会被设置为广播。在后续的续租过程中,DHCP服务器会向客户端发送unicast报文,而不是广播报文。当DHCP服务器同时收到多个请求时,它可能会将offer报文设置为广播,以确保所有客户端都能够接收到该报文。DHCP的offer报文在以下情况下会被设置为广播。

技术的尽头是艺术 433

DHCP option 60 和 option 61

option 60 和 option 61 是2个常见的 DHCP optionoption 60 (Class Id)可以防止非法客户端获取合法ip client 向 DHCP Server 发送 DHCP Discovery 请求,请求中附带 option 60 属性来标示供应商类别标识符。 DHCP Server 检查 option 60 属性,判断发送请求的 Client 是否符合获取IP地

chwzmx123的专栏 4万+
上一篇: udhcp源码详解(四)  之租赁IP的管理
下一篇: HTTP工作原理及报文讲解
JIANXIN.Y
博客等级 码龄9年 273粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值