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

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

原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_SecureTransmissionPlatform_Project07.html