OCI编程高级篇(二十) 使用连接池的例子

OCI编程自学与总结(一) Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 <object class 阅读详情

访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。

这一节我们用代码实现一个实际的例子,来演示连接池的用法。例子中我们仅使用单线程来演示用法,例子的步骤如下。

1. 创建一个OCI环境,分配错误句柄。

2. 创建一个连接池。

3. 从连接池中获取一个会话。

4. 通过这个会话从数据库中查询一个数字,SQL语句为select 10 from dual。

5. 释放会话。

6. 销毁连接池。

7. 释放OCI环境。

例子代码如下,关键处有详细注释。

#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include "memory.h"
#include "string.h"
#include "time.h"
#include "errno.h"

#include "oci.h"


/* global variable defination */
OCIEnv          *envhp  = NULL;         /* env handle */
OCIError        *errhp  = NULL;         /* error handle */
OCISvcCtx       *svchp  = NULL;         /* service context handle */
OCICPool        *poolhp = NULL;         /* connection pool handle */
OCIAuthInfo     *authp  = NULL;         /* authentication information handle */
OCIStmt         *stmthp = NULL;         /* statement handle */

text            errbuf[512];            /* error message text */

struct {
    char        uname[32];              /* 认证用户名称 */
    char        upwd[32];               /* 认证用户密码 */
} inputs;

static void usage(const char *prg)
{
    fprintf(stderr,
        "Usage: %s user/password\n\n"
        "  user      oracle user\n"
        "  password  user password\n"
        , prg
    );
}

/* 解析命令行中的认证用户和密码 */
static int parse_inputs(int argc, char *argv[])
{
    char        *p;

    if (argc < 2) {
      usage(argv[0]);
      return (-1);
    }

    if ((p=strchr(argv[1], '/')) == NULL) {
      usage(argv[0]);
      return (-1);
    }

    *p++ = '\0';
    memset(&inputs, 0, sizeof(inputs));
    strncpy(inputs.uname, argv[1], 31);
    strncpy(inputs.upwd, p, 31);

    return (0);
}

static char ora_env[][16] =
{
  "ORACLE_HOME",
  "ORACLE_SID",
  ""
};

/* 检查Oracle运行的环境变量 */
static int check_ora_env(void)
{
    int         i;

    for (i=0; ora_env[i][0]; i++) {
        if (getenv(ora_env[i]) == NULL) {
            fprintf(stderr, "env %s not set.\n", ora_env[i]);
            return (-1);
        }
    }

    return (0);
}

/* 创建连接池函数 */
static int create_connection_pool(void)
{
    sword       rc;
    sb4         ec;
    ub4         conn_min;
    ub4         conn_max;
    ub4         conn_inc;
    sb4         pool_name_len;
    char        *pool_name;

    /* 创建环境句柄 */
    rc = OCIEnvCreate(
        &envhp,                 /* envhpp */
        OCI_DEFAULT,            /* mode */
        (void *)NULL,           /* ctxp */
        NULL,
        NULL,
        NULL,
        (size_t)0,
        (void **)NULL
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIEnvCreate() - allocate OCI env handle error !\n");
        return (-1);
    }

    /* 分配错误句柄 */
    rc = OCIHandleAlloc(
        (void *)envhp,
        (void **)&errhp,
        OCI_HTYPE_ERROR,
        0,
        (void **)NULL
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIHandleAlloc() - allocate OCI error handle error !\n");
        return (-1);
    }

    /* 分配连接池句柄 */
    rc = OCIHandleAlloc(
        (void *)envhp,
        (void **)&poolhp,
        OCI_HTYPE_CPOOL,
        (size_t)0,
        (void **)NULL
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIHandleAlloc() - allocate connection pool handle error !\n");
        return (-1);
    }

    /* 创建连接池,初始连接数为2,最大连接数为5,每次增长1个连接 */
    conn_min = 2;
    conn_max = 5;
    conn_inc = 1;
    rc = OCIConnectionPoolCreate(
        envhp, errhp, poolhp,
        (OraText **)&pool_name, &pool_name_len,
        (const OraText *)"", 0,
        (ub4)conn_min, (ub4)conn_max, (ub4)conn_inc,
        (OraText *)inputs.uname, strlen(inputs.uname),
        (OraText *)inputs.upwd, strlen(inputs.upwd),
        OCI_DEFAULT
    );

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIConnectionPoolCreate() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 显示一下连接池的名称 */
    fprintf(stdout, "connection pool name: [%d]%s\n", pool_name_len, pool_name);

    return (0);
}

/* 销毁连接池 */
static int destroy_connection_pool(void)
{
    sword       rc;
    sb4         ec;

    /* 销毁连接池 */
    if (poolhp != NULL) {
        rc = OCIConnectionPoolDestroy(poolhp, errhp, OCI_DEFAULT);

        if (rc != OCI_SUCCESS) {
            OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
            fprintf(stderr, "OCIConnectionPoolDestroy() - [%d] %s\n", ec, errbuf);
            return (-1);
        }

        /* 释放连接池句柄 */
        rc = OCIHandleFree((void *)poolhp, OCI_HTYPE_CPOOL);

        if (rc != OCI_SUCCESS) {
            fprintf(stderr, "OCIHandleFree() - free connection pool handle error !\n");
            return (-1);
        }
    }

    /* 释放错误句柄 */
    if (errhp != NULL) {
        rc = OCIHandleFree(
            errhp,
            OCI_HTYPE_ERROR
        );

        if (rc != OCI_SUCCESS) {
            fprintf(stderr, "OCIHandleFree() - free error handle error !\n");
            return (-1);
        }
    }

    /* 释放环境句柄 */
    if (envhp != NULL) {
        rc = OCIHandleFree(
            envhp,
            OCI_HTYPE_ENV
        );

        if (rc != OCI_SUCCESS) {
            fprintf(stderr, "OCIHandleFree() - free env handle error !\n");
            return (-1);
        }
    }

    return (0);
}

/* 从数据库中查询数值 */
static int query_from_dual(void)
{
    sword       rc;
    sb4         ec;
    int         slen;
    ub4         u4;
    char        sqltxt[1024];
    OCIDefine   *defp;

    /* 分配认证信息句柄 */
    rc = OCIHandleAlloc(
        (void *)envhp,
        (void **)&authp,
        OCI_HTYPE_AUTHINFO,
        (size_t)0,
        (void **)NULL
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIHandleAlloc() - allocate authentication handle error !\n");
        return (-1);
    }

    /* 设置认证用户名称 */
    rc = OCIAttrSet(
        (void *)authp,
        OCI_HTYPE_AUTHINFO,
        (dvoid *)inputs.uname,
        strlen(inputs.uname),
        OCI_ATTR_USERNAME,
        errhp
    );

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "Set User Attribute - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 设置认证用户密码 */
    rc = OCIAttrSet(
        (void *)authp,
        OCI_HTYPE_AUTHINFO,
        (void *)inputs.upwd,
        strlen(inputs.upwd),
        OCI_ATTR_PASSWORD,
        errhp
    );

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "Set Password Attribute - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 从连接池获取会话 */
    rc = OCISessionGet(envhp, errhp, &svchp, authp,
        (OraText *)pool_name, pool_name_len,
        NULL, 0, NULL, NULL, NULL,
        OCI_SESSGET_CPOOL
    );

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCISessionGet() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 分配OCI语句句柄 */
    rc = OCIHandleAlloc(
        (void *)envhp,
        (void **)&stmthp,
        OCI_HTYPE_STMT,
        0,
        (void **)NULL
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIHandleAlloc() - allocate statement handle error !\n");
        return (-1);
    }

    /* 产生SQL语句文本 */
    strcpy(sqltxt, "select 10 from dual");
    slen = strlen(sqltxt);

    /* 准备语句 */
    rc = OCIStmtPrepare(stmthp, errhp, (const OraText *)sqltxt, slen,
          OCI_NTV_SYNTAX, OCI_DEFAULT);

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIStmtPrepare() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 定义输出变量 */
    rc = OCIDefineByPos(stmthp,
        &defp,
        errhp,
        (ub4)1,
        (void *)&u4,
        (sb4)4,
        (ub2)SQLT_INT,
        (void *)NULL,
        (ub2 *)NULL,
        (ub2 *)NULL,
        (ub4)OCI_DEFAULT
    );

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIDefineByPos() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 执行查询语句 */
    rc = OCIStmtExecute(svchp, stmthp, errhp, 0, 0, NULL, NULL, OCI_DEFAULT);

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIStmtExecute() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 取回结果集 */
    rc = OCIStmtFetch2(stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIStmtFetch2() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 显示从数据库查询到的数值 */
    fprintf(stdout, "number from dual is: %d\n", u4);

    /* 释放语句句柄 */
    rc = OCIHandleFree(
        stmthp,
        OCI_HTYPE_STMT
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIHandleFree() - free statement handle error !\n");
        return (-1);
    }

    /* 释放连接池会话 */
    rc = OCISessionRelease(svchp, errhp, NULL, 0, OCI_DEFAULT);

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCISessionRelease() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 释放认证信息句柄 */
    rc = OCIHandleFree(
        authp,
        OCI_HTYPE_AUTHINFO
    );

    if (rc != OCI_SUCCESS) {
        fprintf(stderr, "OCIHandleFree() - free authentication handle error !\n");
        return (-1);
     }

    return (0);
}

/* 主函数 */
int main(int argc, char *argv[])
{
    /* 解析命令行参数 */
    if (parse_inputs(argc, argv) < 0)
        return (-1);

    /* 检查Oracle运行环境变量是否设置 */
    if (check_ora_env() < 0)
        return (-1);

    /* 创建连接池 */
    if (create_connection_pool() < 0)
        goto error_exit;

    /* 从数据库中查询数值 */
    if (query_from_dual() < 0)
        fprintf(stderr, "query operation error !\n");

    /* 销毁连接池 */
    destroy_connection_pool();

    return (0);

error_exit:
    destroy_connection_pool();
    return (-1);
}

例子中使用了OCISessionGet()函数来获取连接池会话,要比使用OCILogon2()函数复杂一些,仔细看一下,Oracle提供的示例代码中没有演示OCISessionGet()函数的用法。

Oracle Call Interface (OCI) 示例程序:数据库CRUD操作基础 本文还有配套的精品资源,点击获取 简介:oci.zip文件包含Oracle Call Interface (OCI) 示例,展示了与Oracle数据库交互的CRUD(创建、读取、更新、删除)操作的实现。示例程序以C语言编写,演示了通过oci.h头文件定义的接口与Oracle数据库通信。oci.c或oci.cpp文件包含实现基本数据库操作的源代码,如insert(), sel... 阅读详情

相关推荐

c++ oci接口的简单使用

此文件需要跟官方下载的oci接口头文件,运行环境为linux 32位,需要下载Oracle的相关库并进行配置,根据各人不同情况,配置好,引入oci.h即可。

C函数篇(OCI函数)----oracle编程

原文地址::https://blog.youkuaiyun.com/weixin_30389003/article/details/99630748 相关文章 1、Oracle常用的OCI函数----https://blog.youkuaiyun.com/weixin_34080571/article/details/85483158?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-3&spm=1001.2101.3001.4242 2、O

xqhrs232的专栏 1013

oci 编程教程oci函数的详细介绍

oci函数的详细介绍 和应用实例 OCI 连接过程比较复杂,除了分配设置各个基本句柄外,还要明确彼此之间的联系,大致流程如下: 创建环境句柄: OCIEnvCreate(&envhp;, …); 创建一个指定环境的错误句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp;,…); 创建一个指定环境的服务器句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&servhp;,…); 建立到数据源的访问路径 : OCIServerAttach(servhpp, errhpp,…); 创建一个指定环境的服务上下文句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…); 为指定的句柄及描述符设置特定的属性: (void) OCIAttrSet((dvoid *)svchpp,…); 创建一个指定环境的用户连接句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…); 为用户连接句柄设置登录名及密码: (void) OCIAttrSet((dvoid *)usrhpp,…); 认证用户建立一个会话连接: OCISessionBegin(svchpp, errhpp,…); 创建一个句子句柄: OCIHandleAlloc((dvoid *)envhpp,…);s 准备 SQL 语句: OCIStmtPrepare(stmthpp, errhpp,…); 绑定输入变量: OCIBindByPos(stmtp &hBind;, errhp,…); 绑定输出变量: OCIDefineByPos(stmthpp, &bhp1;, errhpp,…); 获得 SQL 语句类型: OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT,…); 执行 SQL 语句: OCIStmtExecute(svchpp, stmthpp,…); 释放一个会话: OCISessionEnd(); 删除到数据源的访问 : OCIServerDetach(servhpp, errhpp, OCI_DEFAULT); 释放句柄: OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);

通过OCCI操作Oracle数据库详解

1.简介     OCCI 即 Oracle C++ Call Interface          在Windows下访问Oracle数据库可以使用ADO,ADO.Net,OLEDB,ODBC,跨平台的OCCI等方法,其中速度最快,对Oracle支持最完整的是Oracle提供的OCCI.       2.安装OCCI SDK   OCCI SDK包含在Oracle客户端中,在如下位置

rznice的专栏 9219

oci编程示例讲解.pdf

oci编程示例讲解.pdf 结合示例讲解oracle oci编程方法,值得下载。

OCI编程简介

oracle的OCI编程简介,网上的,觉得PDF方便就弄了下来。简单的介绍。

OCI 编程

一、环境的配置  1、系统环境:要想使用OCI编程需要安装Oracle的客户端,而这个普通的客户端比较大,方便起见,可以安装即时客户端(Instantclient)作为Oracle的访问客户端。  具体的配置可以参考这里: http://www.cnblogs.com/ychellboy/archive/2010/04/16/1713884.html 2、执行环境:  windows下...

weixin_34146805的博客 410

oci编程详解.pdf(中文版)

循序渐进的讲解oci编程方法,并结合示例

OCI文档、C++实现例子

一、OCI是什么 ?OCI是一组底层的API(应用程序接口),主要和Oracle数据库进行交互。你可以调用一些操作如 logon , execute, parse, fecth 等等。OCI支持大数据语言,通常使用C/C++。与Oracle Pro*C等不同,OCI不需要预编译。 OCI比Pro*C的一些优势:    OCI的性能十分出色  代码大量缩减  对内置函数直接访问  对LONG

骑猪喝咖啡 1万+

VSCode玩转STM32:手把手教你配置EIDE插件与OpenOCD调试(附野火DAP配置文件详解)

本文详细介绍了如何在VSCode中配置EIDE插件与OpenOCD进行STM32开发,特别针对野火DAP调试器提供了配置文件详解。从基础环境搭建到深度调试技巧,帮助开发者高效完成STM32项目开发,实现现代化嵌入式开发工作流。

weixin_26905487的博客 552

基于PLC的图书馆机器人设计与仿真

本文设计了一种基于PLC的图书馆机器人系统,该系统能提升图书馆自动化管理水平,选用西门子S7-1200系列PLC作为核心控制单元,结合电机驱动、传感器采集以及超声波避障等技术,设计出机器人行走、图书识别与分拣的功能模块,系统借助条形码扫描模块获取图书信息,将其分析后与设定的存放位置做对比,精准达成图书的存取和归还。仿真结果显示,机器人执行任务时运动控制响应时间是0.35秒,避障成功率为98.3%,图书识别准确率高达99.4%,在控制系统方面,运用STEP7-MICRO/WIN软件编程,结合WINCC设计组态

weixin_44553616的博客 1924

OCI编程高级篇(十九) 创建和使用OCI连接池

介绍创建和销毁连接池,获取会话和释放会话等使用连接池的OCI函数,给出了函数原型和参数的解释。

tomcoding的博客 1038

密码学实战:如何利用生日攻击破解哈希函数

本文深入探讨了生日攻击在密码学中的应用及其对哈希函数的威胁。通过分析生日悖论的数学原理,揭示了哈希函数在实际应用中的脆弱性,并提供了防御策略,如升级哈希算法、正确使用加盐技术等。文章结合实战案例,帮助开发者理解如何有效防范此类攻击,确保系统安全。

weixin_42530732的博客 191

OCI 连接池测试

#include "stdafx.h" #include "ocilib.h" #include #include #include #include #include #include #include using namespace std; #pragma comment(lib,"ociliba.lib") #pragma comment(lib,"ocili

冰焰· 3716

uniapp实现app版本发现新版本后,自动更新

app实现自动更新

oldolder的博客 1282

stm32f103c8t6+esp8266在WiFi下通过手机控制外设

stm32f103c8t6+esp8266在WiFi下通过手机控制外设前言 前言 通过上一篇,介绍了esp8266的基本功能,这篇将用stm32c8t6配合esp8266进行数据交互,实现用手机通过无线的方式去控制外设、开关等;这里相当于把stm32作为上一篇的串口助手和esp8266进行通信; ...

weixin_45430735的博客 1万+

OCI编程高级篇(十八) OCI连接池概念

介绍OCI中的连接池概念,使用连接池的步骤。

tomcoding的博客 469

以太网详解(一)-MAC/PHY/MII/RMII/GMII/RGMII基本介绍

网络设备中肯定离开不MAC和PHY,本篇文章将详细介绍下以太网中一些常见术语与接口。 MAC和PHY结构 从硬件角度来看以太网是由CPU,MAC,PHY三部分组成的,如下图示意: 上图中DMA集成在CPU,CPU,MAC,PHY并不是集成在同一个芯片内,由于PHY包含大量模拟器件,而MAC是典型的数字电路,考虑到芯片面积及模拟/数字混合架构的原因,**将MAC集成进CPU而将PHY留在片外,这种...

sternlycore的博客 13万+

OCI编程高级篇(二十一) OCI的线程支持和函数原型

介绍了OCI中使用线程的步骤,线程函数的原型和参数。

tomcoding的博客 835

AI人工智能 Agent:在仓储物流中的应用

AI人工智能 Agent:在仓储物流中的应用 1. 背景介绍 1.1 问题的由来 仓储物流行业是全球经济运行的基石之一,涉及商品的存储、运输、分拣和配送等多个环节。随着电子商务的普及和消费者对物流速度和精确性的要求不断提高,仓储物流

AGI×大数据,开启智能时代的认知跃迁;解码AGI,赋能数据驱动的智能革命。 859

ubuntu20 安装px4、mavros、QGroundControl

首先安装一下ant,否则没法运行,同时因20.04的缺少动态库libawt_xawt.so无法被Java8给调用,我的解决办法是去18.04把18.04的相同路径下的动态库libawt_xawt.so移动到20.04的/usr/lib/jvm/java-11-openjdk-amd64/lib/路径中。用rosdepc的时候,你得确保你用的是鱼香ROS的提供的ROS安装方法,否则是没有rosdepc的。make px4_sitl gazebo之前,可以安装一下gazebo的 模型。二、安装MAVROS。

qq_58060770的博客 3346

linux c oci 远程连接例子

以下是我的测试oci的例子!#include #include #include #include "oci.h"static OCIServer        *srvhp;static OCISession       *p_session;static OCIEnv           *p_env;static OCIError         *p_err;static OCIS

zhangyinze123的专栏 3557

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

OCI编程高级篇(八) LOB写操作

介绍OCI写入LOB的步骤,从打开LOB到关闭LOB,中间的写操作可以是流模式,也可随机写入,一个完整的示例代码演示写入过程。

tomcoding的博客 834

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

OCI编程高级篇(二十二) OCI多线程编程和示例代码

OCI多线程编程的实际例子,介绍了多线程怎样使用连接池的,哪些函数在主线程调用,哪些函数在子线程中调用。

tomcoding的博客 380

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Oracle连接池oci,Oracle数据库的连接(OCI方式、thin方式和JdbcOdbc桥方式、l连接池)

在J2EE应用程序开发中,应用程序与数据库连接的建立是我们经常遇到的问题之一。在这里我主要谈谈在本地应用程序中通过OCI方式、thin方式和JdbcOdbc桥方式连接Oracle数据库,在iPlanetApplicationServer6.5和SunJavaSystemApplicationServer7中对Oracle数据库连接池的配置以及应用中如何从连接池中获得连接一、本地通过...

weixin_28750663的博客 1482
上一篇: OCI编程高级篇(十九) 创建和使用OCI连接池
下一篇: OCI编程高级篇(二十一) OCI的线程支持和函数原型
tomcoding
博客等级 码龄9年 410粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值