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,转载请注明出处。

  • 相关阅读:
    1044 拦截导弹
    3060 抓住那头奶牛 USACO
    2727:仙岛求药(广搜)
    4906 删数问题(另一种贪心思路)
    1004 四子连棋
    1005 生日礼物
    1031 质数环
    1008 选数
    1073 家族
    2801 LOL-盖伦的蹲草计划
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_SecureTransmissionPlatform_Project07.html
Copyright © 2011-2022 走看看