【无标题】
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是协议,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中定义的数据类型既有简单的基本数据类型,也有复杂的结构类型。
- 基本类型是不可再再分的,包括:
- 布尔型(BOOLEAN)
- 整型(INTEGER)
- 实型(REAL)
- 位串类型(BITSTRING)
- 8位位组类型(OCTET STRING)
- 枚举类型(ENUMERATED)
- 空类型(NULL)
- 对象标识符(OBJECT IDENTIFIER)
- 除基本类型,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连接池;断链修复;跨平台;粘包;
技术基础:
- 从linux内核的角度,理解三次握手和四次断开(全双工)
- 主动套接字和被动套接字,accept的函数
- 连接的概念
- 长连接和短链接实现的条件
- 客户端主动
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 两个配置文件
- tnsnames.ora?
- 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 |
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!