数据安全传输基础设施平台(三)

6安全传输平台实现

6.1报文编解码组件设计与实现

6.1.1常见报文类型

超文本传输协议

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1。

1. Request和Response的格式

Request格式:

HTTP请求行

(请求)头

空行

可选的消息体

注:请求行和标题必须以<CR><LF> 作为结尾(也就是,回车然后换行)。空行内必须只有<CR><LF>而无其他空格。在HTTP/1.1 协议中,所有的请求头,除Host外,都是可选的。

实例:

GET / HTTP/1.1

Host: gpcuster.cnblogs.com

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-us,en;q=0.5

Accept-Encoding: gzip,deflate

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Keep-Alive: 300

Connection: keep-alive

If-Modified-Since: Mon, 25 May 2009 03:19:18 GMT

Response格式:

HTTP状态行

(应答)头

空行

可选的消息体

实例:

HTTP/1.1 200 OK

Cache-Control: private, max-age=30

Content-Type: text/html; charset=utf-8

Content-Encoding: gzip

Expires: Mon, 25 May 2009 03:20:33 GMT

Last-Modified: Mon, 25 May 2009 03:20:03 GMT

Vary: Accept-Encoding

Server: Microsoft-IIS/7.0

X-AspNet-Version: 2.0.50727

X-Powered-By: ASP.NET

Date: Mon, 25 May 2009 03:20:02 GMT

Content-Length: 12173

空行

­消息体的内容(略)

HTML

文本标记语言,即HTML(Hypertext Markup Language),是用于描述网页文档的一种标记语言。

一个网页对应于一个HTML文件,HTML文件以.htm或.html为扩展名。可以使用任何能够生成TXT类型源文件的文本编辑来产生HTML文 件。 超文本标记语言标准的HTML文件都具有一个基本的整体结构,即HTML文件的开头与结尾标志和HTML的头部与实体2大部分。有3个双标记符用于页面整 体结构的确认。

<html>

<head>

<title>Document name goes here</title>

</head>

<body>

Visible text goes here   404 file not found

</body>

</html>

<a href="http://www.example.com/">This is a Link</a>

<a href="http://www.example.com/"><img src="URL"

alt="Alternate Text"></a>

<a href="mailto:webmaster@example.com">Send e-mail</a>A named anchor:

<a name="tips">Useful Tips Section</a>

<a href="#tips">Jump to the Useful Tips Section</a>

HTML文本标记语言,即HTML(Hypertext Markup Language),是用于描述网页文档的一种标记语言。
HTML是一种规范,一种标准,它通过标记符号来标记要显示的网页中的各个部分。
http 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收 HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。 Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1。

总结:HTML是超文本标记语言,HTTP是协议,HTML在HTTP协议上运行的;通过HTTP协议也可以传输声音、图像、数据。等等。

XML报文

XML为Extensible Markup Language的缩写,即可扩充标注语言。它是由SGML所精简而来的一种通用标注语言,主要是要简化SGML烦杂的结构,强化HTML过于简单而不够严谨的语法。微软是XML技术的推动者之一,它希望能够建立一个可以为WWW 广泛使用语言环境,推动程序的兼容与协同,从而降低成本,刺激增长。

虽然XML创立之初只是被当作一项基础技术,但其发展早已超出设计者原先的构想。不论是学术界还是商业界都将其视为下一代网络的基石。XML现在已经成为一股不可抵挡的技术潮流。

现有的XML主要应用在四个方面:一是应用于具有不同复杂格式的不同数据源间的交互;二是应用于大量运算负荷分布在客户端的情况,用户可以根据自己的需求选择和制作不同的应用程序以处理数据,而服务器只需发出同一个XML文件;三是应用于将同一数据以不同的形式表现出来;四是应用于网络代理对所取得的信息进行编辑、增减以适应个人用户的需要,形成具有个人特色的数据文件。

事实上,XML技术的潜能还远未被充分挖掘。据一份最新的研究指出,以XML为基础的内容生命周期产品,将在今后5年以10倍的速度快速成长,在2008年达到116亿美元的营业规模。以XML和Web服务为主的研究公司Zap Think在研究报告中也指出,这些以XML为基础并包括Web服务的工具,是将旧有系统再度激活的新希望。

“XML最大的影响在于XML软件大量兴起:XML剖析器、XML程序语言库、XSLT处理器、XSL FO处理器、数据库接受XML——不只如此,还有网络浏览器也接受XML。”XML工作小组创始会员C.M. Sperberg-McQueen如是认为。也正因为如此,IBM、微软、SUN、惠普、Oracle等大公司纷纷进入这个市场。

而在XML最大应用之一的数据格式转换领域,Adobe、微软、Core都在各自相关的软件产品中充分利用了XML技术。以程序关联为特色的Office 2003更是将XML的格式转换特性发挥到了极致,以至于这个软件套装几乎成为了一个独立的数据系统。

<!DOCTYPE project [

  <!ENTITY Common SYSTEM "common.xml">

%Common;

]>

<!--

  Bouncy Castle Build Configuration (midp)

  This is the JDK 1.1 specific build file.  

  $RCSfile: jdk11.xml,v $

  $Author: bouncy $

  $Date: 2005/07/06 13:02:52 $

  $Revision: 1.1.1.1 $

-->

<project name="jdk11" default="init" basedir=".">

<property environment="env" />

<property file="${env.CRYPTO_PROP}" />

<!-- Public callable targets -->

<target name="clean" depends="common-clean" />

<target name="test" depends="common-test" />

<target name="dist" depends="common-dist" />

<target name="package" depends="common-package" />

<target name="compile" depends="init, local-compile" />

<target name="jdoc" depends="common-jdoc" />

<!-- include common targets, properties -->

<property name="master.jdk" value="jdk11" />

&Common;

<!-- ** Private properties -->

<patternset id="jdk11.lw-compatibility" >

<include name="java/**" />

</patternset>

<patternset id="jdk11.jce-compatibility">

<include name="org/**" />

</patternset>

<patternset id="jdk11.lw-extras" >

<include name="org/bouncycastle/crypto/test/*.java" />

</patternset>

<patternset id="orgbc.javax">

<include name="javax/**" />

</patternset>

<patternset id="orgbc.lw-source" >

<include name="org/bouncycastle/math/ec/*.java" />

<include name="org/bouncycastle/crypto/**" />

<include name="org/bouncycastle/util/**" />

<include name="org/bouncycastle/asn1/**" />

</patternset>

<patternset id="orgbc.jce-source" >

<include name="org/bouncycastle/jce/**" />

<exclude name="org/bouncycastle/jce/netscape/*" />

<exclude name="org/bouncycastle/jce/provider/X509CertificateObject.java" />

<exclude name="org/bouncycastle/jce/provider/RSAUtil.java" />

<exclude name="org/bouncycastle/jce/provider/JDKX509CertificateFactory.java" />

<exclude name="org/bouncycastle/jce/provider/test/RSATest.java" />

<exclude name="org/bouncycastle/jce/provider/test/RegressionTest.java" />

<!-- to make the friggin thing compile -->

<exclude name="org/bouncycastle/jce/provider/test/DSATest.java" />

<exclude name="org/bouncycastle/jce/provider/test/DHTest.java" />

<exclude name="org/bouncycastle/jce/provider/test/Netscape*.java" />

<exclude name="org/bouncycastle/jce/provider/test/Named*.java" />

</patternset>

<property name="build.compiler" value="classic" />

<property name="bcp" value="${env.JAVA_HOME}/lib/classes.zip" />

<path id="compile.cp">

<pathelement location="${master.classes}" />

<pathelement location="${bcp}" />

</path>

<target name="local-compile" depends="llw-compile, ljce-compile" />

<!-- extra targets used in this file -->

<target name="llw-compile" if="is.lw">

<echo message="jdk11.lw-compatibility" />

<javac srcdir="${master.home}/jdk1.1"

destdir="${master.classes}"

includeAntRuntime="no"

includeJavaRuntime="no"

debug="off"

optimize="off"

target="1.1">

<patternset refid="jdk11.lw-compatibility" />

<classpath refid = "compile.cp" />

</javac>

<echo message="orgbc.lw-source" />

<javac srcdir="${master.src}"

destdir="${master.classes}"

includeAntRuntime="no"

includeJavaRuntime="no"

debug="off"

optimize="off"

target="1.1">

<patternset refid="orgbc.lw-source" />

<classpath refid = "compile.cp" />

</javac>

</target>

<target name="ljce-compile" if="is.jce" >

<!-- cheat a bit here to remove duplication -->

<antcall target="llw-compile">

<param name="is.lw" value="true" />

</antcall>

<!-- now do the extra bits for the JCE -->

<echo message="orgbc.jce-source" />

<javac srcdir="${master.src}"

destdir="${master.classes}"

includeAntRuntime="no"

includeJavaRuntime="no"

debug="off"

optimize="off"

target="1.1">

<patternset refid="orgbc.javax" />

<patternset refid="orgbc.jce-source" />

<classpath refid = "compile.cp" />

</javac>

<echo message="jdk11.jce-compatibility" />

<javac srcdir="${master.home}/jdk1.1"

destdir="${master.classes}"

includeAntRuntime="no"

includeJavaRuntime="no"

debug="off"

optimize="off"

target="1.1">

<patternset refid="jdk11.jce-compatibility" />

<classpath refid = "compile.cp" />

</javac>

</target>

</project>

JSON

JSON,全称是JavaScript Object Notation。它是基于JavaScript编程语言ECMA-262 3rd Edition-December 1999标准的一种轻量级的数据交换格式,主要用于用于跟服务器进行交换数据。跟XML相类似,它独立于语言,在跨平台数据传输上有很大的优势。

上面是百科的解释,可以说明json大概的意思和作用,json其实就是键值对存储数据,举个例子:

var a ={"one":"一","two":"二","three":"三"},a就是一个json,a.one的值就是一,还可以内嵌数组

var b={"A":"[1,2,3,4,5,6,7]","B":"[a,b,c,d,e]"},b.A[0]的值就是1,json变量里面还可以内嵌json,可以内嵌数组,取值方法就是如上面的那种,数组用下标,json取键值对的名,使用起来很方便,数据存储格式简洁

自定义

struct Teacher

{

char name[32]; 

int age;

char desc[1024]

char *p //32 64

}

Aaaaahtol(31)XXXXXXXXXXXXXXX

32-------aaaa================ 

ASN.l抽象语法标记

ASN.1抽象语法标记(Abstract Syntax Notation One) ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序。

ASN.1是描述在网络上传输信息格式的标准方法。它有两部分:一部分描述信息内数据,数据类型及序列格式;另一部分描述如何将各部分组成消息。它原来是作为X.409的一部分而开发的,后来才自己独立成为一个标准。ASN.1在OSI的ISO 8824/ITU X.208(说明语法)和ISO 8825/ITU X.209(说明基本编码规则)规范。

例如:

Report ::= SEQUENCE {

author OCTET STRING,

title OCTET STRING,

body OCTET STRING,

biblio Bibliography

}

在这个例子中,"Report"是由名字类型的信息组成的,而SEQUENCE表示消息是许多数据单元构成的,前三个数据单元的类型是OCTET STRING,而最后一个数据类型见下面的ASN.1语法表示它的意义:

Bibliography ::= SEQUENCE {

author OCTET STRING

title OCTET STRING

publisher OCTET STRING

year OCTET STRING

}

ASN.1中定义的数据类型既有简单的基本数据类型,也有复杂的结构类型。

  1. 基本类型是不可再再分的,包括:
    • 布尔型(BOOLEAN)
    • 整型(INTEGER)
    • 实型(REAL)
    • 位串类型(BITSTRING)
    • 8位位组类型(OCTET STRING)
    • 枚举类型(ENUMERATED)
    • 空类型(NULL)
    • 对象标识符(OBJECT IDENTIFIER)
  2. 除基本类型,ASN.1还定义了多种复杂的结构类型,例如:
    • SEQUENCE:有序的数据集合(序列),由不同类型的数据组成。SEQUENCE结构强调内部成员的排序
    • SEQUENCE OF:有序的数据集合,类似于C语言的数组,由同一类型的数据组成。
    • SET:由不同类型的数据组成的集合,用来描述复杂的信息对象,对内部成员的顺序不作要求,类似于C语言的结构体类型 
    • CHOICE:选择结构,在列出的内部成员中,只能选择其中之一,类似于C语言中的共用体类型

6.1.2ASN.1编码解码 

typedef struct _Teacher

{

char name[64];

int age ;

char *p;

int plen;

}Teacher;

int mywritefile(unsigned char *buf, int len)

{

FILE *fp = NULL;

fp = fopen("c:/teacher.ber","wb+");

if(fp == NULL)

{

printf("fopen file error \n");

return -1;

}

fwrite(buf, 1, len, fp);

fclose(fp);

return 0;

}

int TeacherEncode(Teacher *pStuct, unsigned char **out, int *outlen)

{

}

int TeacherDecode(unsigned char *inData, int inLen, Teacher **pStruct)

{

}}

结构体编码原理图: 

老师结构编码样例: 

案例2:问题抛出,若100个结构体,如何对报文进行统一报文编码解码;实现业务流和基础组件的解耦合。

6.1.3报文编码组件设计与实现

重点:深入理解,报文编码解码组件和业务流模块的解耦合

统一报文编码解码设计思想

3 编码实现统一报文组件的编码业务流

4 编码实现统一报文组件的解码业务流程

5 优化统一报文组件 日志/内存泄漏

6 统一报文组件动态库 和 动态库测试程序

7 统一报文组件 linux下的移植 跨平台的移植

Win系统文件上传/linux系统文件编译/动态库工程makefile和动态库文件

#ifndef _KEYMNG_MSG_H_

#define _KEYMNG_MSG_H_

#ifdef __cplusplus

extern "C" {

#endif

#define KeyMng_ParamErr 200 //输入参数失败

#define KeyMng_TypeErr 201 //输入类型失败

#define KeyMng_MallocErr 202 //分配内存失败

#define KeyMng_NEWorUPDATE 1 //1 密钥更新

#define KeyMng_Check 2 //2 密钥校验

#define KeyMng_Revoke 3 //3 密钥注销

  ;

#define  ID_MsgKey_Req  60

//密钥请求报文

typedef struct _MsgKey_Req

{

//1 密钥更新   //2 密钥校验; //3 密钥注销

int cmdType; //报文命令码

char clientId[12]; //客户端编号

char AuthCode[16]; //认证码

char serverId[12]; //服务器端I编号

char r1[64]; //客户端随机数

}MsgKey_Req;

//密钥应答报文

#define  ID_MsgKey_Res  61

typedef struct  _MsgKey_Res

{

int rv; //返回值

char clientId[12]; //客户端编号

char serverId[12]; //服务器编号

unsigned char r2[64]; //服务器端随机数

}MsgKey_Res;

/*

 pstruct : 输入的报文数据 ; (指向相应结构体的指针)

 type : 输入的类型标识(函数内部通过type 得到 pstruct 所指向的报文类型)

 poutData: 输出的编码后的报文 ;

 outlen : 输出的数据长度;

*/

int MsgEncode(

void *pStruct , /*in*/

int type,

unsigned char **outData, /*out*/

int *outLen );

/*

 inData : 输入的编码后的数据;

 inLen : 输入的数据长度 ;

 pstruct : 输出的解码后的数据; (其空间是在内部开辟的,也需要用内部定义的free函数进行释放)

 type : 结构的类型标识(返回类型标识,使得调用者通过flag进行判断,将pstruct 转换为相应的结构)

*/

int MsgDecode(

unsigned char *inData,/*in*/

int           inLen,

void          **pStruct /*out*/,

int           *type /*out*/);

/*

释放 MsgEncode( )函数中的outData; 方法:MsgMemFree((void **)outData, 0);

释放MsgDecode( )函数中的pstruct结构体,MsgMemFree((void **)outData, type);

type : 输入参数,便于函数判断调用哪个结构体的free函数

*/

int MsgMemFree(void **point,int type);

#ifdef __cplusplus

}

#endif

#endif

统一报文编码解码样例 

6.2统一通讯组件设计与实现

6.2.1统一通讯组件接口设计

项目开发对通讯组件的要求

上层业务流和基础组件的合理分层

Win和linux异构、跨平台

稳定性

连接的处理(短链接、长连接)

公网:断链修复

公网:粘包处理

入门的关键:连接

解决的问题:稳定、易用;长连接短链接,socket连接池;断链修复;跨平台;粘包;

技术基础:

  1. 从linux内核的角度,理解三次握手和四次断开(全双工)
  2. 主动套接字和被动套接字,accept的函数
  3. 连接的概念
  4. 长连接和短链接实现的条件
    1. 客户端主动

b) 服务器端配合

c)问题:服务器端是如何判断对方已经关闭了那?

5)socket连接池的设计理念

6.2.2统一通讯组件接口实现

#ifndef _poolsocket_H_

#define _poolsocket_H_

#ifdef __cplusplus

extern 'C'

{

#endif

//错误码定义  

#define Sck_Ok              0

#define Sck_BaseErr    3000

#define Sck_ErrParam                  (Sck_BaseErr+1)

#define Sck_ErrTimeOut                (Sck_BaseErr+2)

#define Sck_ErrPeerClosed              (Sck_BaseErr+3)

#define Sck_ErrMalloc      (Sck_BaseErr+4)

#define Sck_Err_Pool_CreateConn (Sck_BaseErr+20)  //创建连接池 (没有达到最大连接数)

#define Sck_Err_Pool_terminated (Sck_BaseErr+21) //已终止

#define Sck_Err_Pool_GetConn_ValidIsZero (Sck_BaseErr+22) //有效连接数是零

#define Sck_Err_Pool_HaveExist (Sck_BaseErr+22) //连接已经在池中

#define Sck_Err_Pool_ValidBounds (Sck_BaseErr+22) //有效连接数目超过了最大连接数

//客户端 初始化

int sckClient_init();

//客户端 连接服务器

int sckClient_connect(char *ip, int port, int connecttime, int *connfd);

//客户端 关闭和服务端的连接

int sckClient_closeconn(int connfd);

//客户端 发送报文

int sckClient_send(int connfd, int sendtime, unsigned char *data, int datalen);

//客户端 接受报文

int sckClient_rev(int connfd, int revtime, unsigned char **out, int *outlen); //1

//客户端 释放内存

int sck_FreeMem(void **buf);

//客户端 释放

int sckClient_destroy();

typedef struct _SCKClitPoolParam

{

char serverip[64];

int serverport;

int bounds; //池容量

int connecttime;

int sendtime;

int revtime;

}SCKClitPoolParam;

//客户端 socket池初始化

int sckCltPool_init(void **handle, SCKClitPoolParam *param);

//客户端 socket池 获取一条连接

int sckCltPool_getConnet(void *handle, int *connfd);

//客户端 socket池 发送数据

int sckCltPool_send(void *handle, int  connfd,  unsigned char *data, int datalen);

//客户端 socket池 接受数据

int sckCltPool_rev(void *handle, int  connfd, unsigned char **out, int *outlen); //1

//客户端 socket池 把连接放回 socket池中

int sckCltPool_putConnet(void *handle, int connfd, int validFlag); //0正常 1

//客户端 socket池 销毁连接

int sckCltPool_destroy(void *handle);

//函数声明

//服务器端初始化

int sckServer_init(int port, int *listenfd);

int sckServer_accept(int listenfd, int timeout, int *connfd);

//服务器端发送报文

int sckServer_send(int connfd, int timeout, unsigned char *data, int datalen);

//服务器端端接受报文

int sckServer_rev(int  connfd, int timeout, unsigned char **out, int *outlen); //1

int sckServer_close(int connfd);

//服务器端环境释放

int sckServer_destroy();

#ifdef __cpluspluse

}

#endif

#endif

6.3 共享内存操作组件设计与实现

6.3.1共享内存基本API

基本操作

查看共享内存

Ipcs

操作共享内存

[it01@localhost ~]$ ipcrm -m

ipcrm:选项需要一个参数 -- m

ipcrm: illegal option -- ?

usage: ipcrm [ [-q msqid] [-m shmid] [-s semid]

           [-Q msgkey] [-M shmkey] [-S semkey] ... ]

案例:第1个应用程序读共享内存,第2个应用程序写共享内存;第3个删除共享内存。会出现什么现象。

Linux内核管理共享内存的机制

6.3.2共享内存组件设计与实现

// myipc_shm.h

#ifndef _WBM_MY_SHM_H_

#define _WBM_MY_SHM_H_

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#ifdef __cplusplus

extern "C" {

#endif

//共享内存错误码

#define MYIPC_OK 0 //正确

#define MYIPC_ParamErr 301 //输入参数失败

#define MYIPC_NotEXISTErr 302 //共享内存不存在错误

#define MYIPC_CreateErr 303 //创建共享内存错误

//创建共享内存 若共享内存不存在,则创建

int IPC_CreatShm(int key, int shmsize, int *shmhdl);

//打开共享内存 若共享内存不存在,返回错误

int IPC_OpenShm(int key, int shmsize, int *shmhdl);

/***********************************************************************

  功能描述:    创建共享内存 通过种子文件

  参数说明:    shmname  [in]  是共享内存名,系统中唯一标志

                shmsize  [in]  是要创建的共享内存的大小;

                shmhdl   [out] 共享内存的句柄.

  返回值:      返回0函数执行成功;非0返回错误码

************************************************************************/

int IPC_CreatShmBySeedName(char *shmname, int shmsize, int *shmhdl);

/***********************************************************************

  功能描述:    关联共享内存

  参数说明:    shmhdl [in]  共享的句柄

                mapaddr [out] 共享内存首地址

  返回值:      返回0函数执行成功;非0返回错误码

************************************************************************/

int IPC_MapShm(int shmhdl,void **mapaddr);

/***********************************************************************

  功能描述:    取消共享内存关联

  参数说明:    unmapaddr   [in] 共享内存首地址

  返回值:      返回0函数执行成功;非0返回错误码

************************************************************************/

int IPC_UnMapShm(void *unmapaddr);

/***********************************************************************

  功能描述:    删除共享内存

  参数说明:    shmhdl [in]  共享的句柄

  返回值:      返回0函数执行成功;非0返回错误码

************************************************************************/

int IPC_DelShm(int shmhdl);

#ifdef __cplusplus

}

#endif

#endif

6.4 服务器框架设计与实现

6.4.1SecMngclient和SecMngServer总体业务流设计

 

客户端和服务器密钥协商流程

//产生随机数

//产生密钥序号

//新协商的密钥写入数据库

//新协商的密钥写入共享内存

//应答密钥协商报文

客户端和服务器密钥密钥校验流程

//读服务器 共享内存 获取密钥信息

//校验密钥信息

//组织应答报文 编码应答报文

//发送应答报文

客户端和服务器密钥注销流程

6.4.2SecMngClient设计和实现

SecMngClient集成报文编解码组件
SecMngClient集成通讯组件
SecMngClient集成共享内存组件
SecMngClient集成日志组件

//服务器端 密钥协商流程

//服务器端,共享内存管理约定

//1 共享内存创建和使用

// 通过keymngserver创建服务器端共享内存,keymngserver创建共享内存根据最大网点数来创建

// keymngserver启动时,若共享内存已经存在,则不创建,也不恢复以前的共享内存数据

// keymngserver启动时,若共享内存不存在,则创建共享内存,也不恢复以前的共享内存数据

// 外联接口做业务时,需要通过keymngclient和keymngserver重新协商密钥后,再做业务

//2 共享内存删除

// 重新启动系统,则共享内存消失

// 管理员手工删除共享内存(软件运行中,不能删除共享内存,否则外联接口异常)

//3 共享内存更新

// 客户端和服务器端的协商密钥,可以通过客户端的进行更新

//4 服务器端密钥协商流程

//产生随机数

//产生密钥序号

//新协商的密钥写入数据库

//新协商的密钥写入共享内存

//应答密钥协商报文

void *thread_routine(void* arg)

{

unsigned char *recvbuf = NULL;

int recvbuflen = 0;

int   connfd;

int ret = 0;

void* reqMsg = NULL; //请求报文

  int reqMsgType = 0; //请求报文类型

  unsigned char* sendBuf = NULL; //发送报文缓冲区

    int sendBufLen = 0; //发送报文缓冲区长度

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[2], ret,"func thread_routine() begin");

connfd = *((int *)arg);

free(arg);  //64bit系统下 指针是8个字节

while(1)

{

recvbuf = NULL;

recvbuflen = 0;

reqMsg = NULL; //请求报文

reqMsgType = 0; //请求报文类型

sendBuf = NULL; //发送报文缓冲区

sendBufLen = 0; //发送报文缓冲区长度

//对方已关闭 超时 错误

ret = sckServer_rev(connfd, 3, &recvbuf, &recvbuflen);

if (ret == Sck_ErrPeerClosed)

{

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"业务线程中, func sckServer_rev() err, 对方已关闭");

break;

}

else if (ret == Sck_ErrTimeOut)

{

//KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"业务线程中, func sckServer_rev() err, timeout 超时");

continue;

}

else if (ret != 0)

{

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"业务线程中, func sckServer_rev() err, 接受报文失败");

//发送错误应答报文

continue;

}

//解析请求报文

ret = MsgDecode(recvbuf, recvbuflen, &reqMsg, &reqMsgType);

if (ret != 0)

{

sck_FreeMem((void **)&recvbuf);

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func MsgDecode() err");

//发送错误应答报文

continue;

}

//4 处理请求 根据业务类型  组织应答报文

ret = KeyMng_OpReal(reqMsg, reqMsgType, &sendBuf, &sendBufLen);

if (ret != 0)

{

sck_FreeMem((void **)&recvbuf);

MsgMemFree((void **)&reqMsg, reqMsgType);

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func MsgDecode() err");

//发送错误应答报文

continue;

}

//5 发送应答报文

ret = sckServer_send(connfd, 3, sendBuf, sendBufLen);

if (ret != 0)

{

sck_FreeMem((void **)&recvbuf);

MsgMemFree((void **)&reqMsg, reqMsgType);

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func sckServer_send() err");

break;

}

sck_FreeMem((void **)&recvbuf);

MsgMemFree((void **)&reqMsg, reqMsgType);

}

sckServer_close(connfd);

KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[2], ret,"func thread_routine() end");

pthread_exit(0);

}

集成共享内存组件

6.4.3SecMngServer设计和实现

SecMngServer处理流程

 

ecMngServer集成通信组件
SecMngServer集成共享内存组件
SecMngServer集成数据库组件

6.4.4SecMngClient和SecMngServer对接调试

1 密钥协商 服务器DER报文编码错误

表面现象  客户端收报文超时

定位问题

通过日志

通过gdb调试

解决问题

2 密钥协商 服务器端写oracle数据库错误

定位问题

通过日志

通过gdb调试

解决问题

6.5数据传输平台数据库设计

6.5.1oracle数据库使用常见问题

1 oracle用户启动oracle服务器

2 在linux环境中,用sqlplus工具访问oracle服务

在oracle用户下,用sqlplus访问oracle服务  scott/aa

在非oracle用户下,用sqlplus访问oracle服务 scott/aa

Chmod 777 /home/oracle_11/app –R

同时配置.bash_profile

3 在win环境中,用sqlplus工具访问linux环境下的oracle服务

1 Ping 192.168.43.252

2 telnet 192.168.43.252 1521  防火墙没有把端口给封住

//防火墙 linux服务器 1521 端口 放开

3 两个配置文件

  1. tnsnames.ora 
  2. listener.ora

6.5.2数据传输平台数据库脚本

参考数据库脚本。

6.6统一数据接口组件设计与实现

6.6.1数据库接口设计思想

基于连接池的数据库访问方案  

6.6.2数据库接口实现

#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);

/********************************************************/

/*程 序 名: IC_DBApi_ConnGet */

/*功能描述: 从连接池获取数据库连接 */

/*参数说明: handle 数据库连接句柄 */

/* sTimeout 超时时间(秒) */

/* nsTimeout 超时时间(毫秒) */

/********************************************************/

int IC_DBApi_ConnGet(ICDBHandle* handle, int sTimeout, int nsTimeout);

/********************************************************/

/*程 序 名: IC_DBApi_ConnFree */

/*功能描述: 释放数据库连接到连接池 */

/*参数说明: handle 数据库连接句柄 */

/* validFlag 数据库连接有效性 */

/********************************************************/

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_CONNECTION_ERR -3113 //与数据库的连接错误

#define IC_DB_CONNECTION2_ERR -3114 //与数据库的连接错误

#ifdef __cplusplus

}

#endif

#endif

6.7客户端框架MFC设计与实现

6.7.1主框架搭建

VC++实现的QQ主窗口抽屉菜单效果,应该说是一个面板吧,可以展开和折叠起来,Outlook 中也有类似的界面,和OICQ 的主界面非常相似

视图的切分

1)通过AppWizard 生成单文档单视图的应用程序SecMngAdmin

2)添加外部文件.h.cpp

将文件GFXGROUPEDIT.CPP  GFXGROUPEDIT.H  

GFXOUTBARCTRL.CPP GFXOUTBARCTRL.H

GFXPOPUPMENU.CPP   GFXPOPUPMENU.H

gfxPub.h  GFXSPLITTERWND.CPP   GFXSPLITTERWND.H  拷贝到项目工程目录下,然后再通过vc编译器,添加现有文件功能,添加到项目中。

编译上述文件,发现失败如下:

3)添加外部光标文件

在资源文件中引入3 个光标文件,表示鼠标进行不同操作时光标的形状,其ID 分别为IDC_HANDLECUR、IDC_DRAGGING 和IDC_NODRAGGING。

4)在resource.h中添加控件消息宏定义

把在Resource.h文件加入如下代码,定义控件的消息

#define ID_GFX_SMALLICON 50000

#define ID_GFX_LARGEICON 50001

#define ID_GFX_RENAMEITEM 50002

#define ID_GFX_REMOVEITEM 50003

#define ID_GFX_GROUPICON 50004

#define ID_GFX_FONTCICON 50005

#define ID_GFX_BACKCICON 50006

典型错误1

//DWORD dwVersion = ::GetVersion();

DWORD dwVersion = 4;

BOOL bWin4 = (BYTE)dwVersion >= 4;

bNotWin4 = 1 - bWin4;   // for convenience

m_upBorder = 8;

bWhiteLine = true;

错误 1 error C4996: 'GetVersion': 被声明为已否决 d:\users\qiaojn\documents\visual studio 2013\projects\mysecadmin_1\mysecadmin_1\gfxsplitterwnd.cpp 45 1 MySecAdmin_1

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值