zoukankan      html  css  js  c++  java
  • 安全传输平台项目——密钥协商设计与实现--数据库操作

    在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    10-安全传输平台项目-第07天(密钥协商设计与实现--数据库操作)

    目录:
    一、复习
    二、安全传输平台项目——密钥协商设计与实现--数据库操作
    1、数据库-启动回顾
    2、数据库-SQL语句回顾
    3、数据库-事务回顾
    4、数据库-显示中文问题
    5、数据库-函数接口设计
    6、游标说明
    7、数据库-proc说明
    8、数据库-访问API
    9、数据库-非查询语句API使用
    10、数据库-错误调试
    11、数据库-查询语句API
    12、数据库-行存储内存模型打造
    13、数据库-操作接口
    14、数据库-base64编码和函数注意事项

    一、复习

    1、密钥协商共享内存
    2、守护进程
    3、脚本

    二、安全传输平台项目——密钥协商设计与实现--数据库操作

    1、数据库-启动回顾

    》数据启动:
        1. su - oracle (不允许使用root 启动 oracle 数据库)
        2. sqlplus /nolog
        3. connect / as sysdba
        4. startup
        5. show suer; (select * from scott.dept)    quit;
        6. 在命令行中 lsnrctl start

    注意:如果未启动lsnrctl start,无法在外部借助第三方工具(如:SQL Developer)访问数据库。

    2、数据库-SQL语句回顾

    》SQL语句:

        查询:
            select * from 表 where 条件。
            select deptno, dname, loc from dept where deptno = 20;

        删除:
            delete from 表 where 条件。
            delete from dept where deptno = 99;

       插入:
            insert into 表(deptno, dname) values(50, 'Engineer') ;
            insert into dept values(60, 'Engineer', 'Beijing');

        更新:
            update 表 set 列名=列新值 [,列名=列新值] where 条件。
            update dept set dname='Engineer', loc = 'Beijing' where deptno=60;

    3、数据库-事务回顾

    》事务:
        要么都成功、要么都失败。
        4大特性:持久性、隔离性、原子性、一致性。

        DCL:commit; rollback; savepoint;
        DDL:create; truncate; grant; alter; revoke;
        DML:insert/update/delete/select  --- curd

        开启:
            oracle 默认自动开启事务。    ---mySQL 可以设置手动开启。   

        关闭:
            显式关闭:
                commit; rollback;
            隐式关闭:
                quit;执行DDL语句时
            异常:宕机、掉电。。。 --- rollback;

    4、数据库-显示中文问题

    一般需要查看

    1)echo $LANG

    2)cat /etc/sysconfig/i18n

    3)vi .bash_profile

    注释掉(或者改为NLS_LANG = UTF-8)保存退出后,执行>source .bash_profile 生效。

    注意:如果只在test04用户下更改.bash_profile,切换到oracle用户后查看表中数据仍然中文乱码!

    4)如果都解决不了,只能重启数据库!


    扩:字符集的问题?NLS_LANG后的字符集要与数据库的默认的字符集对应,否则可能会乱码

    NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集
    》数据库的字符集(props$):
    set linesize 300
    set pagesize 300
    select * from nls_database_parameters;

    select userenv('language') from dual;

    》客户端字符集(v$parameter)
    select * from nls_instance_parameters;

    》会话字符集(v$nls_parameters)
    select * from nls_session_parameters;

    》查看linux服务器字符集
    echo $LANG
    env |grep LANG

    》设置LANG
    查看LANG    env | grep LANG
    设置LANG    export LANG=zh_CH.GBK

    LANG是针对Linux系统的语言、地区、字符集的设置。
    NLS_LANG是针对Oracle语言、地区、字符集的设置。

    在使用zhs16gbk时SourceCRT会话设置字符集为 gb18030


    5、数据库-函数接口设计

    》问题抛出:如何在单位时间内提高客户端与服务器的通信效率?

    服务器(epoll、select、多路I/O转接、线程池、libevent库等)优化的再好,只能当前服务器并发事件的处理的能力,也要考虑客户端(扩大通信带宽(如:用户级缓冲区的大小)、socket通信(提高连接数,如:连接池))

    》客户端数据库连接池:

        所有的数据库访问操作,都是典型的 C/S ---- socket
        int clitPool_init(int num, char *dbuser, char *dbpasswd, char *dbname, void **handle);
        int clitPool_GetConn(void *handle);

    无结果集:
        int clitPool_NoResutl(void *handle, char *sql);

        int clitPool_StartTrans(void *handle);

    结果集:
        int clitPool_HaveResutl(void *handle, char *sql, void **outResult);

        游标: (不知道返回的结果集-表 的长度为多少,所以使用游标
            while (1) {
                fatch 数据(当调用游标fatch时,取出一行结果集的同时,游标往下移动一行
            }
        int clitPool_createCursor(void *handle, char *sql, void **cursor);
        int clitPool_openCursor(void *cursor, void **outResult);
        int clitPool_fetchData(void *cursor, void *Row); --> while 中
        int clitPool_closeCursor(void *cursor);   
      int clitPool_CommitTrans(void *handle);
      int clitPool_RollbackTrans(void *handle);
      int clitPool_PutConn(void *handle);
      int clitPool_destroy(void *handle);

    6、游标说明

    普通游标  滚动游标   两种。
          获取第一行
          获取最后一行
          获取相对第N行  
          获取绝对第N行

    》游标使用一般步骤:

        1. 创建一个游标        --- 游标一定是为某一次查询而生的。( select语句 )

        2. 打开游标        --- 当游标成功打开,(1)标志着结果集已经存储至客户端本地。
                                            (2)标志着游标已经指向结果集中的首行

        3. fetch 提取数据    --- 一次fetch 只能提取一行数据。 一定要结合 while 循环。 找结束点  Oracle1403 、MySQL100

        4. 关闭游标。

    7、数据库-proc说明

    icdbapi.h对应lib下的libicdbapi.so(以及内部使用的libclntsh.so)

    》proc:

    8、数据库-访问API

    >vi icdbapi.h

    #ifndef _IC_DBApi_H_
    #define _IC_DBApi_H_
    
    
    #ifdef  __cplusplus
    extern "C" {
    #endif
    
    
    #ifndef ICDBHandle
    #define ICDBHandle            void*
    #endif
    
    #ifndef ICDBCursor
    #define ICDBCursor            void*
    #endif
    
    #ifndef ICDBLob
    #define ICDBLob                void*
    #endif
    
    
    #define ICDBBLOB            0
    #define ICDBCLOB            1
    #define ICDBNCLOB            2
    
    #define MAXBLOBDATALEN        1024
    
    
    #ifndef ICDBField
    typedef struct _ICDBField
    {
        char*    cont;
        int        contLen;
    }ICDBField;
    #endif
    
    #ifndef ICDBRow
    typedef struct _ICDBRow
    {
        ICDBField*    field;
        int            fieldCount;
    }ICDBRow;
    #endif
    
    
    /*实际使用的Level(如果[1]=0或1(debug),[2]=0或2(info),[3]=0或3(warning),[4]=0或4(error)),为0则表示不写相应的日志*/
    //extern int  IC_DB_DTUseLevel[5];
    extern int  DTORADBLevel[5];
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_PoolInit                        */
    /*功能描述:    数据库连接池初始化                        */
    /*参数说明:    bounds        连接池容量                    */
    /*                dbName        数据库名称                    */
    /*                dbUser        数据库用户                    */
    /*                dbPswd        数据库用户口令                */
    /********************************************************/
    int IC_DBApi_PoolInit(int bounds, char* dbName, char* dbUser, char* dbPswd);
    
    
    // SECMNG/SCEMNG@orcl
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_ConnGet                        */
    /*功能描述:    从连接池获取数据库连接                    */
    /*参数说明:    handle        数据库连接句柄                */
    /*                sTimeout    超时时间(秒)                */
    /*                nsTimeout    超时时间(毫秒)                */
    /********************************************************/
    int IC_DBApi_ConnGet(ICDBHandle* handle, int sTimeout, int nsTimeout);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_ConnFree    实际对应ConnPut        */
    /*功能描述:    释放数据库连接到连接池                    */
    /*参数说明:    handle        数据库连接句柄                */
    /*                validFlag    数据库连接有效性        1    */
    /********************************************************/
    int IC_DBApi_ConnFree(ICDBHandle handle, int validFlag);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_PoolFree                        */
    /*功能描述:    释放数据库连接池                        */
    /*参数说明:                                            */
    /********************************************************/
    int IC_DBApi_PoolFree();
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_ExecNSelSql                    */
    /*功能描述:    执行单个非select数据库语句(不包含事务)    */
    /*参数说明:    handle        数据库连接句柄                */
    /*                sql            数据库语句                    */
    /********************************************************/
    int IC_DBApi_ExecNSelSql(ICDBHandle handle, char* sql);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_ExecNSelSqls                    */
    /*功能描述:    执行多个非select数据库语句(包含事务)    */
    /*参数说明:    handle        数据库连接句柄                */
    /*                sqls        数据库语句(以NULL结束)        */
    /********************************************************/
    int IC_DBApi_ExecNSelSqls(ICDBHandle handle, char* sqls[]);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_BeginTran                     */
    /*功能描述:    数据库事务开始                          */
    /*参数说明:    handle      数据库连接句柄              */
    /********************************************************/
    int IC_DBApi_BeginTran(ICDBHandle handle);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_Rollback                        */
    /*功能描述:    数据库事务回退                            */
    /*参数说明:    handle        数据库连接句柄                */
    /********************************************************/
    int IC_DBApi_Rollback(ICDBHandle handle);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_Commit                        */
    /*功能描述:    数据库事务提交                            */
    /*参数说明:    handle        数据库连接句柄                */
    /********************************************************/
    int IC_DBApi_Commit(ICDBHandle handle);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_ExecSelSql                    */
    /*功能描述:    执行select数据库语句(返回单条记录)        */
    /*参数说明:    handle        数据库连接句柄                */
    /*                sql            数据库语句                    */
    /*                row            返回的记录                    */
    /********************************************************/
    int IC_DBApi_ExecSelSql(ICDBHandle handle, char* sql, ICDBRow* row);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_ExecSelSqlMR                  */
    /*功能描述:    执行select数据库语句(返回多条记录)      */
    /*参数说明:    handle      数据库连接句柄              */
    /*              sql         数据库语句                  */
    /*              beginNo     返回记录的开始条数          */
    /*              count       返回记录的条数              */
    /*                rows        返回的记录                    */
    /*              allRecNum   符合条件的记录总数          */
    /********************************************************/
    int IC_DBApi_ExecSelSqlMR(ICDBHandle handle, char* sql, int beginNo, int count, ICDBRow* rows, int* allRecNum);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_OpenCursor                    */
    /*功能描述:    打开游标                                */
    /*参数说明:    handle      数据库连接句柄              */
    /*              sql         数据库语句                  */
    /*              fieldCount  字段个数                    */
    /*              pCursor     游标指针                    */
    /********************************************************/
    int IC_DBApi_OpenCursor(ICDBHandle handle, char* sql, int fieldCount, ICDBCursor* pCursor);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_FetchByCursor                 */
    /*功能描述:    通过游标获取数据                        */
    /*参数说明:    handle      数据库连接句柄              */
    /*              cursor      游标                           */
    /*                row            返回的记录                    */
    /********************************************************/
    int IC_DBApi_FetchByCursor(ICDBHandle handle, ICDBCursor cursor, ICDBRow* row);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_CloseCursor                   */
    /*功能描述:    关闭游标                                */
    /*参数说明:    handle      数据库连接句柄              */
    /*              pCursor     游标指针                    */
    /********************************************************/
    int IC_DBApi_CloseCursor(ICDBHandle handle, ICDBCursor* pCursor);
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_Pem2Der                        */
    /*功能描述:    PEM编码转DER编码                        */
    /*参数说明:    pemData     PEM数据                      */
    /*              pemDataLen  PEM数据长度                    */
    /*              derData     DER数据                        */
    /*              derDataLen  DER数据长度                    */
    /********************************************************/
    int IC_DBApi_Pem2Der(char* pemData, int pemDataLen, unsigned char* derData, int* derDataLen);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_Der2Pem                        */
    /*功能描述:    PEM编码转DER编码                        */
    /*参数说明:    derData     DER数据                      */
    /*              derDataLen  DER数据长度                    */
    /*              pemData     PEM数据                        */
    /*              pemDataLen  PEM数据长度                    */
    /********************************************************/
    int IC_DBApi_Der2Pem(unsigned char* derData, int derDataLen, char* pemData, int* pemDataLen);
    
    
    /********************************************************/
    /*程 序 名:    IC_DBApi_GetDBTime                        */
    /*功能描述:    获取数据库时间                            */
    /*参数说明:    handle      数据库连接句柄              */
    /*              dbTime       数据库时间                     */
    /********************************************************/
    int IC_DBApi_GetDBTime(ICDBHandle handle, char* dbTime);
    
    
    
    #define IC_DB_BASE_ERR                        17000
    
    #define IC_DB_OK                            0
    #define IC_DB_NODATA_AFFECT                    100
    
    #define IC_DB_PARAM_ERR                        IC_DB_BASE_ERR+1    //SQLDA初始化错误
    #define IC_DB_SQLDAINIT_ERR                    IC_DB_BASE_ERR+1    //SQLDA初始化错误
    #define IC_DB_SQLRELEASE_ERR                IC_DB_BASE_ERR+2    //提交事务并释放连接语句错误
    #define IC_DB_SQLALTERDATE_ERR                IC_DB_BASE_ERR+3    //修改连接的时间格式语句错误
    #define IC_DB_SQLCONNECT_ERR                IC_DB_BASE_ERR+4    //连接数据库语句错误
    #define IC_DB_PTHREAD_MUTEX_INIT_ERR        IC_DB_BASE_ERR+5    //初始化互斥错误
    #define IC_DB_PTHREAD_COND_INIT_ERR            IC_DB_BASE_ERR+6    //初始化条件错误
    #define IC_DB_SQLENABLETHREADS_ERR            IC_DB_BASE_ERR+7    //设置使用线程语句错误
    #define IC_DB_MALLOC_ERR                    IC_DB_BASE_ERR+8    //分配内存错误
    #define IC_DB_CONTEXTALLOCATE_ERR            IC_DB_BASE_ERR+9    //为连接句柄分配内存语句错误
    #define IC_DB_CONNECT_ERR                    IC_DB_BASE_ERR+10    //数据库连接错误
    #define IC_DB_PTHREAD_MUTEX_LOCK_ERR        IC_DB_BASE_ERR+11    //获取互斥锁错误
    #define IC_DB_ALLCONN_NOTVALID_ERR            IC_DB_BASE_ERR+12    //连接池所有连接都是无效连接错误
    #define IC_DB_CONDTIMEOUT_ERR                IC_DB_BASE_ERR+13    //获取连接超时错误
    #define IC_DB_PTHREAD_COND_TIMEDWAIT_ERR    IC_DB_BASE_ERR+14    //线程条件超时等待函数错误
    #define IC_DB_POOLTERMINATED_ERR            IC_DB_BASE_ERR+15    //连接池已经终止错误
    #define IC_DB_GETCOND_VALIDISZERO_ERR        IC_DB_BASE_ERR+16    //获取条件后有效连接仍未0错误
    #define IC_DB_PTHREAD_MUTEX_UNLOCK_ERR        IC_DB_BASE_ERR+17    //释放互斥锁错误
    #define IC_DB_VALIDBOUNDS_ERR                IC_DB_BASE_ERR+18    //有效连接数大于最大容量错误
    #define IC_DB_NVALIDBOUNDS_ERR                IC_DB_BASE_ERR+19    //无效连接数大于最大容量错误
    #define IC_DB_POOL_WAKEALL_ERR                IC_DB_BASE_ERR+20    //唤醒所有连接的阻塞状态错误
    #define IC_DB_SQLEXECIMMEDIAT_ERR            IC_DB_BASE_ERR+21    //立即执行SQL语句错误
    #define IC_DB_COMMIT_ERR                    IC_DB_BASE_ERR+22    //事务提交语句错误
    #define IC_DB_ROLLBACK_ERR                    IC_DB_BASE_ERR+23    //事务回退语句错误
    #define IC_DB_PREPARESTMT_ERR                IC_DB_BASE_ERR+24    //准备查询语句错误
    #define IC_DB_DESCRIBESELECT_ERR            IC_DB_BASE_ERR+25    //填充SQLDA语句错误
    #define IC_DB_FIELDCOUNT_ERR                IC_DB_BASE_ERR+26    //输入的字段数目错误
    #define IC_DB_FIELDNULL_ERR                    IC_DB_BASE_ERR+27    //输入的字段为空错误
    #define IC_DB_SETROWDATAMEMORY_ERR            IC_DB_BASE_ERR+28    //为字段设置存贮空间错误
    #define IC_DB_DECLARECURSOR_ERR                IC_DB_BASE_ERR+29    //定义游标语句错误
    #define IC_DB_OPENCURSOR_ERR                IC_DB_BASE_ERR+30    //打开游标语句错误
    #define IC_DB_FETCH_ERR                        IC_DB_BASE_ERR+31    //通过游标获取数据语句错误
    #define IC_DB_CLOSECURSOR_ERR                IC_DB_BASE_ERR+32    //关闭游标语句错误
    #define IC_DB_INPUT_ERR                        IC_DB_BASE_ERR+33    //输入条件错误
    #define IC_DB_GETROWCOUNT_ERR                IC_DB_BASE_ERR+34    //获取符合条件的记录总数错误
    #define IC_DB_LOBDESCRIBE_ERR                IC_DB_BASE_ERR+35    //获取原有LOB数据属性语句错误
    #define IC_DB_LOBWRITE_ERR                    IC_DB_BASE_ERR+36    //往LOB字段写数据语句错误
    #define IC_DB_ALLOCATELOB_ERR                IC_DB_BASE_ERR+37    //分配BLOB语句错误
    #define IC_DB_LOBREAD_ERR                    IC_DB_BASE_ERR+38    //从LOB字段读数据语句错误
    #define IC_DB_LOBFREE_ERR                    IC_DB_BASE_ERR+39    //释放LOB语句错误
    #define IC_DB_LOBCLOSE_ERR                    IC_DB_BASE_ERR+40    //关闭LOB语句错误
    #define IC_DB_LOBNOTOPEN_ERR                IC_DB_BASE_ERR+41    //Lob没有打开错误
    #define IC_DB_LOBOPEN_ERR                    IC_DB_BASE_ERR+42    //打开LOB错误
    #define IC_DB_SQLEXECBEGINWORK_ERR            IC_DB_BASE_ERR+43    //开始事务错误
    #define IC_DB_SQLGETTIME_ERR                IC_DB_BASE_ERR+44    //获取数据库时间错误
    
    /*#define                 IC_DB_BASE_ERR+        //错误
    #define                 IC_DB_BASE_ERR+45    //错误
    #define                 IC_DB_BASE_ERR+46    //错误
    #define                 IC_DB_BASE_ERR+47    //错误
    #define                 IC_DB_BASE_ERR+48    //错误
    #define                 IC_DB_BASE_ERR+49    //错误*/
    
    #define IC_DB_CONNECTION_ERR                -3113                    //与数据库的连接错误
    #define IC_DB_CONNECTION2_ERR                -3114                    //与数据库的连接错误
    
    
    #ifdef __cplusplus
    }
    #endif
    
    
    #endif
    icdbapi.h

    需要记忆的错误号:

    #define IC_DB_CONNECT_ERR                    IC_DB_BASE_ERR+10    //数据库连接错误

    9、数据库-非查询语句API使用

    >vi noSelect_dbapi.c

    #include <unistd.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <pthread.h>
    
    #include "icdbapi.h"
    
    int main(void)
    {
        int ret = 0;
        int bounds = 10;
        char *dbName = "orcl";
        char *dbUser = "SCOTT";
        char *dbPswd = "11";
        char mySql[2048] = {0};
        
        ICDBHandle handle = NULL;//void * -- ICDBHandle
        
        //初始化 数据库连接池
        ret = IC_DBApi_PoolInit(bounds, dbName, dbUser, dbPswd);
        if(ret != 0)
        {
            printf("func IC_DBApi_PoolInit() err:%d
    ", ret);
            return ret;
        }
        
        ret = IC_DBApi_ConnGet(&handle, 0, 0);
        if(ret != 0)
        {
            printf("func IC_DBApi_ConnGet() err:%d
    ", ret);
            return ret;
        }
        
        ret = IC_DBApi_BeginTran(handle);
        if(ret != 0)
        {
            printf("func IC_DBApi_BeginTran() err:%d
    ", ret);
            goto END;
        }
        
        strcpy(mySql, "insert into dept(deptno, dname, loc) values(92, '92name姓名', '92loc城市')");
        
        //执行sql语句 2类错误 1类:执行sql语句失败  2:链接断开
        ret = IC_DBApi_ExecNSelSql(handle, mySql); //insert update
        if(ret != 0)
        {
            printf("func IC_DBApi_ExecNSelSql() err:%d
    ", ret);
            goto END;
        }
        
        if(ret == 0)
        {
            IC_DBApi_Commit(handle);
        }
        else
        {
            IC_DBApi_Rollback(handle);
        }
        
    END:
        //validFlag 1:不需要修复,0:需要断链修复
        if(ret == IC_DB_CONNECT_ERR)//把链接放到连接池
        {
            IC_DBApi_ConnFree(handle, 0);//需要断链修复
        }
        else
        {
            IC_DBApi_ConnFree(handle, 1);//不需要断链修复
        }
        
        IC_DBApi_PoolFree();
        
        printf("hello dbapi...
    ");
        return 0;
    }
    noSelect_dbapi.c

    >vi test.c

    #include <unistd.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <pthread.h>
    
    #include "icdbapi.h"
    
    int main(void)
    {
        int ret = 0;
        int bounds = 10;
        char *dbName = "orcl";
        char *dbUser = "scott";
        char *dbPswd = "11";
    
        
        ICDBHandle handle = NULL;//void * -- ICDBHandle
        
        //初始化 数据库连接池
        ret = IC_DBApi_PoolInit(bounds, dbName, dbUser, dbPswd);
        if(ret != 0)
        {
            printf("func IC_DBApi_PoolInit() err:%d
    ", ret);
            return ret;
        }
        
        //从连接池中获取一条连接
        ret = IC_DBApi_ConnGet(&handle, 0, 0);
        if(ret != 0)
        {
            printf("func IC_DBApi_ConnGet() err:%d
    ", ret);
            return ret;
        }
        
        //开启事务
        ret = IC_DBApi_BeginTran(handle);
        if(ret != 0)
        {
            printf("func IC_DBApi_BeginTran() err:%d
    ", ret);
            goto END;
        }
        
        //拼接sql语句
        //char mySql[2048] = {0};
        //strcpy(mySql, "insert into dept(deptno, dname, loc) values(92, '92name姓名', '92loc城市')");
        char *sql = "insert into dept values(92, '92name姓名', '92loc城市');";
        
        //执行sql语句 2类错误 1类:执行sql语句失败  2:链接断开
        ret = IC_DBApi_ExecNSelSql(handle, mySql); //insert update
        if(ret != 0)
        {
            printf("func IC_DBApi_ExecNSelSql() err:%d
    ", ret);
            goto END;
        }
        
        //根据ret  commit 或者rollback
        if(ret == 0)
        {
            IC_DBApi_Commit(handle);
        }
        else
        {
            IC_DBApi_Rollback(handle);
        }
        
    END:
        //释放链接,断链修复
        //validFlag 1:不需要修复,0:需要断链修复
        if(ret == IC_DB_CONNECT_ERR)//把链接放到连接池
        {
            IC_DBApi_ConnFree(handle, 0);//需要断链修复
        }
        else
        {
            IC_DBApi_ConnFree(handle, 1);//不需要断链修复
        }
        
        IC_DBApi_PoolFree();
        
        printf("hello dbapi...
    ");
        return 0;
    }
    test.c

    >make

    >./test

    因为调用了...so,所以可以产生日志,在log下查看日志:

    打开另一个终端,执行shell>oerr ora 911

    分析:由于分号“;”导致的,去掉“;”后重新编译执行:

    打开第三个终端,登录数据库,查看插入是否成功:

    注意:中文乱码的问题!

    10、数据库-错误调试

    》错误调试:
        日志:    log : 错误级别。 时间。
        命令:    oerr ora  错误号(去除负号)    ( proc --> oracle --> c/c++ )
     

    1)连续执行(插入)会报错?

    在log下查看日志(icdbapi_20170704.log):

    打开另一个终端,执行shell>oerr ora 1

    2)密码改错char *dbPswd = "tiger"?

    重新编译执行会阻塞,Ctrl+c会出现报错:

    在log下查看日志(icdbapi_20170704.log):

    打开另一个终端,输入 >oerr ora 1017

    尝试把密码改回“11”,重新编译执行,仍然报错:

    在log下查看日志(icdbapi_20170704.log):

    打开另一个终端,输入 >oerr ora 28000

    注意: 连接池中,错误用户名、密码反复连接,会锁定用户。

    》连接池错误连接示意图:

    解决:如果忘记解锁密码指令(alter user scott),可以借助SQL Developer工具:

    重新执行> ./test,就可以插入数据了。

    11、数据库-查询语句API

    >vi select_dbapi.c

    #include <unistd.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <pthread.h>
    
    #include "icdbapi.h"
    
    int main(void)
    {
        int ret = 0;
        int bounds = 10;
        char *dbName = "orcl";
        char *dbUser = "scott";
        char *dbPswd = "11";
        
        ICDBHandle handle = NULL;//void * -- ICDBHandle
        ICDBCursor cursor = NULL;
        
        int deptno = 0;
        char dname[24];
        char loc[24];
        
        ICDBRow row;
        ICDBField field[10];
        
        memset(&row, 0, sizeof(ICDBRow));
        memset(field, 0, sizeof(ICDBField)*3);
        
        field[0].cont = (char *)&deptno;
        field[0].contLen = 4;
        
        field[1].cont = (char *)dname;
        field[1].contLen = 24;
        
        field[2].cont = (char *)loc;
        field[2].contLen = 24;
        
        //打造内存关系
        row.field = field;
        row.fieldCount = 3;
        
        //初始化 数据库连接池
        ret = IC_DBApi_PoolInit(bounds, dbName, dbUser, dbPswd);
        if(ret != 0)
        {
            printf("func IC_DBApi_PoolInit() err:%d
    ", ret);
            return ret;
        }
        
        //从连接池中获取一条连接
        ret = IC_DBApi_ConnGet(&handle, 0, 0);
        if(ret != 0)
        {
            printf("func IC_DBApi_ConnGet() err:%d
    ", ret);
            return ret;
        }
        
        //拼接sql语句
        char mySql[2048] = {0};
        strcpy(mySql, "select * from dept");
        //或者:char *sql = "insert into dept values(92, '92name姓名', '92loc城市')";
        
        //游标 是为某一次查询而生 dept是3列
        //创建同时打开游标
        ret = IC_DBApi_OpenCursor(handle, mySql, 3, &cursor);
        if(ret != 0)
        {
            printf("func IC_DBApi_OpenCursor() err:%d
    ", ret);
            goto END;
        }
        
        //打印表头
        printf("%s	%s	%s	
    ", "deptno", "dname", "loc");
        
        while(1)
        {
            deptno = 0;//数据内存重新初始化
            memset(dname, 0, sizeof(dname));
            memset(loc, 0, sizeof(loc));
            
            ret = IC_DBApi_FetchByCursor(handle, cursor, &row);//一次提取一行,存入row中
            if(ret == 100 || ret == 1403) //IC_DB_NODATA_AFFECT
            {
                break;
            }
            else
            {
                printf("%d	%s	%s	
    ", deptno, dname, loc);
            }
        }
        
        IC_DBApi_CloseCursor(handle, cursor);
        
    END:
        //释放链接,断链修复
        //validFlag 1:不需要修复,0:需要断链修复
        if(ret == IC_DB_CONNECT_ERR)//把链接放到连接池
        {
            IC_DBApi_ConnFree(handle, 0);//需要断链修复
        }
        else
        {
            IC_DBApi_ConnFree(handle, 1);//不需要断链修复
        }
        
        //释放初始化环境
        IC_DBApi_PoolFree();
        
        printf("dbapi finish...
    ");
        
        return 0;
    }
    select_dbapi.c

    >make

    >./select_dbapi

    12、数据库-行存储内存模型打造

    》内存模型—分析select_dbapi.c代码中row和游标:

    13、数据库-操作接口

    》密钥协商:
        ——Agree:
    开启事务
            1. 从数据库 keysn 表中取出 seckeyid 。                     ---读数据库。select --keysn
            2. 将 自增后的 seckeyid 存入 keysn表中。                ---写数据库。update --keysn        --seckeyid
            3. 将写入共享内存中的 NodeSHMInfo 写入数据库 表 seckeyinfo 中。        ---写数据库。insert --seckeyinfo     
    关闭事务

    》密钥校验:
        ——Check:
            --- 读数据库。 select --seckeyinfo

    》密钥注销:
        ——Revoke:
            --- 写数据库。 update --seckeyinfo

    >keymng_dbop.h

    // keymng_dbop.h
    #ifndef _KEYMNG_DBOP_H_
    #define _KEYMNG_DBOP_H_
    
    #include "keymngserverop.h"
    #include "keymng_shmop.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    int KeyMngsvr_DBOp_GenKeyID(void *dbhdl, int *keyid);
    
    int KeyMngsvr_DBOp_WriteSecKey(void *dbhdl, NodeSHMInfo *pNodeInfo); 
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    keymng_dbop.h

    >keymng_dbop.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <pthread.h>
    
    #include "keymng_dbop.h"
    #include "keymngserverop.h"
    #include "keymnglog.h"
    #include "icdbapi.h"
    
    //读keysn表 更新ikeysn列 +1 ---> seckeyid 
    int KeyMngsvr_DBOp_GenKeyID(void *dbhdl, int *keyid)
    {
        int             ret = 0;
        int             ikeysn;
        
        ICDBRow         row;
        ICDBField       field[7];
        
        char            mysql1[1024];
        char            mysql2[1024];
    
        memset(field, 0, sizeof(field));
        memset(mysql1, 0, sizeof(mysql1));   
           memset(mysql2, 0, sizeof(mysql2));   
    
        if (dbhdl== NULL || keyid==NULL)
        {
            ret = -1;
            KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func KeyMngsvr_DBOp_GenKeyID() err");
               goto END;
        }
        
        sprintf(mysql1, "select ikeysn from SECMNG.KEYSN for update ");//使用sql锁 for update  
        
        // 读取序列号累加器
        field[0].cont = (char *)&ikeysn;
                    
        row.field = field;
        row.fieldCount = 1;    
        
        // 累加器加1 
        sprintf(mysql2,"update SECMNG.KEYSN set ikeysn = ikeysn + 1");  
        
        ret = IC_DBApi_ExecSelSql(dbhdl, mysql1, &row);    
        if (ret != 0)
        {
            KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func IC_DBApi_ExecSelSql() err,
     sql:%s", mysql1);
            goto END;    
        }
            
        ret =  IC_DBApi_ExecNSelSql(dbhdl, mysql2); //执行单个非select语言
        if (ret != 0)
        {
            KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func IC_DBApi_ExecNSelSql() err, sql:%s", mysql2);
            goto END;
        }
        
         *keyid = ikeysn;
      
    END:
        
        return ret;
    }
    
    //写密钥  插入共享内存结构体 到数据库   seckinof
    int KeyMngsvr_DBOp_WriteSecKey(void *dbhdl, NodeSHMInfo *pNodeInfo) 
    {
        int         ret = 0;
        char        mysql[2048] = {0};
        
        char        optime[24]  = {0};
        char        tmpseckey2[1024];
        int            tmplen = 1024;
        char         buf2[1024];
        
        memset(tmpseckey2, 0, sizeof(tmpseckey2));
        memset(mysql, 0, sizeof(mysql));
        
        // 获取当前操作时间
        ret = IC_DBApi_GetDBTime(dbhdl, optime);
        if (ret != 0)
        {
            KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func IC_DBApi_GetDBTime() err");
               goto END;
        }
        
        // base64 编码 Oracle 9i
        ret = IC_DBApi_Der2Pem( pNodeInfo->seckey, sizeof(pNodeInfo->seckey) , tmpseckey2, &tmplen );
        if (ret != 0)
        {
            KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func IC_DBApi_Der2Pem() err
    ");
               goto END;
        }
    
        //组织sql语句
        sprintf(mysql, "Insert Into SECMNG.SECKYEINFO(clientid, serverid, keyid, createtime, state, seckey) 
                        values ('%s', '%s', %d, '%s', %d, '%s') ", pNodeInfo->clientId,  pNodeInfo->serverId, 
                        pNodeInfo->seckeyid, optime, 0, tmpseckey2 );
       
        //执行非select sql语句
        ret = IC_DBApi_ExecNSelSql(dbhdl, mysql);
        if (ret != 0)
        {
            KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret, "func IC_DBApi_ExecNSelSql() err 
     sql===>%s
    ", mysql);
            goto END;
        }
      
     END:    
        return ret;
    }
    
    //测试PEM和DER互转
    int IC_DBApi_Pem2Der_Test2()
    {
        int                 rv = -1;
        char             str[1024];
        char             strPem[1024];
        unsigned char     strDer[1024];
        int                 strPemLen = 1024;
        int                 strDerLen = 1024;
        
        memset(str, 0, 1024);
        memset(strPem, 0, 1024);
        memset(strDer, 0, 1024);
        
        printf("请输入要从DER转化为PEM的字符串:");
        //fgets(str, 256, stdin);
    //    scanf("%s", str);
    //    while(getchar() != '
    ');
    
        strcpy(str, "abcdefg");
        
        //DER2PEM
        rv = IC_DBApi_Der2Pem((unsigned char*)str, strlen(str), strPem, &strPemLen);
        if(rv)
        {
            printf("DER2PEM ERROR!
    ");
            return rv;
        }
        else
        {
            printf("DER2PEM OK!PEM is %s
    ", strPem);
        }
        
        //PEM2DER
        rv = IC_DBApi_Pem2Der(strPem, strPemLen, strDer, &strDerLen);
        if(rv)
        {
            printf("PEM2DER ERROR!
    ");
            return rv;
        }
        else
        {
            printf("PEM2DER OK!DER is %s
    ", strDer);
        }
        
        return 0;
    }
    keymng_dbop.c

    14、数据库-base64编码和函数注意事项

    1)去掉keymngserverop.c中seckeyid全局静态变量及自增的操作,加入KeyMngsvr_DBOp_GenKeyID(void *dbhdl, int *keyid)函数

    2)将原来的密钥seckey转码为tmpseckey2写入数据库?

    seckey  r1 64 r2 64 --> 128 (不一定是可见字符)

    》base64编码:
        3x8 = 4x6
        10010101    11011010    10010101
        00100101    00011101    00101010    00010101  --->  可见字符。
        A-Z、a-z 0-9、+、/ 、=(只会出现在结尾)
        26 + 26 + 10 + 2 = 64

    》oracle数据类型:
        varchar2: oracle 9i    ---> 2048 --- 4096
            必须是可见字符。
        blob --> Oracle 数据类型转码。可以mp3转码后存入
        clob --> Oracle 数据类型转码。可以mp4转码后存入

    3)如果多个客户端同时(并发访问)与服务器建立连接,怎么保证读取和写入的数据统一呢?采用线程同步机制吗?

    数据库采用了SQL锁解决了这个问题,select ikeysn from SECMNG.KEYSN for update后边加入for update(告诉数据库像执行update语句那样执行select)

    4)初始化数据库连接池int IC_DBApi_PoolInit(int bounds, char* dbName, char* dbUser, char* dbPswd);加入到哪 进行数据库连接池创建?

    keymngserverop.c中int MngServer_InitInfo(MngServer_Info * svrInfo);函数中当服务器初始化了数据库名,用户名,用户密码,连接池的数量,初始化共享内存后加入IC_DBApi_PoolInit进行数据库连接池初始化(创建)。

    5)"update SECMNG.KEYSN set ikeysn = ikeysn + 1"语句?

    等号左侧的ikeysn是列名,等号右侧的是变量名。所以变量本身的值不会改变!

    在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    623. Add One Row to Tree 将一行添加到树中
    771. Jewels and Stones 珠宝和石头
    216. Combination Sum III 组合总数三
    384. Shuffle an Array 随机播放一个数组
    382. Linked List Random Node 链接列表随机节点
    向github项目push代码后,Jenkins实现其自动构建
    centos下安装Jenkins
    python提取批量文件内的指定内容
    批处理实现:批量为文件添加注释
    python抓取每期双色球中奖号码,用于分析
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_SecureTransmissionPlatform_Project07.html
Copyright © 2011-2022 走看看