安全传输平台项目——密钥协商设计与实现--数据库操作
在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主: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
需要记忆的错误号:
#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\n", ret); return ret; } ret = IC_DBApi_ConnGet(&handle, 0, 0); if(ret != 0) { printf("func IC_DBApi_ConnGet() err:%d\n", ret); return ret; } ret = IC_DBApi_BeginTran(handle); if(ret != 0) { printf("func IC_DBApi_BeginTran() err:%d\n", 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\n", 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...\n"); return 0; }
>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\n", ret); return ret; } //从连接池中获取一条连接 ret = IC_DBApi_ConnGet(&handle, 0, 0); if(ret != 0) { printf("func IC_DBApi_ConnGet() err:%d\n", ret); return ret; } //开启事务 ret = IC_DBApi_BeginTran(handle); if(ret != 0) { printf("func IC_DBApi_BeginTran() err:%d\n", 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\n", 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...\n"); return 0; }
>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\n", ret); return ret; } //从连接池中获取一条连接 ret = IC_DBApi_ConnGet(&handle, 0, 0); if(ret != 0) { printf("func IC_DBApi_ConnGet() err:%d\n", 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\n", ret); goto END; } //打印表头 printf("%s\t%s\t%s\t\n", "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\t%s\t%s\t\n", 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...\n"); return 0; }
>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.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,\n 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\n"); 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 \n sql===>%s\n", 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() != '\n'); strcpy(str, "abcdefg"); //DER2PEM rv = IC_DBApi_Der2Pem((unsigned char*)str, strlen(str), strPem, &strPemLen); if(rv) { printf("DER2PEM ERROR!\n"); return rv; } else { printf("DER2PEM OK!PEM is %s\n", strPem); } //PEM2DER rv = IC_DBApi_Pem2Der(strPem, strPemLen, strDer, &strDerLen); if(rv) { printf("PEM2DER ERROR!\n"); return rv; } else { printf("PEM2DER OK!DER is %s\n", strDer); } return 0; }
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,转载请注明出处。
posted on 2020-07-29 18:38 Alliswell_WP 阅读(465) 评论(1) 编辑 收藏 举报