1 开始使用zBox-SDK
Microsoft Windows、 Microsoft Visual Studio 2008、 Visual AssistX、 mysql-connector-odbc
1.2、zBox-SDK配置运行
将下载的zBox-SDK解压放入D盘,如 D:\lnkSvr\bin\
bin目录下的debug是开发环境,release是生产环境。
下载配置文件ini.7z开发测试环境放入debug,生产环境放入release目录,并做相应的配置修改
debug或release目录的lnkHttpSvr.exe是Web服务软件,配置好ini文件双击即可运行。通常我们在开发环境使用调试运行,在生产环境安装成window服务运行。
1.3、使用一个简单demo工程调试运行
下载zbox_project_demo.zip放入wwwroot目录,用Microsoft Visual Studio 2008打开ProjectTest.vcproj
右键项目->选择属性->设置调试参数,按F5运行
2 基于zBox-SDK开发应用程序的运行原理
B/S(Brower/Server)结构
1、工程文件在B/S结构模式下的分布和运行:
1).所有工程文件最终都是放到服务器端,浏览器发送请求到服务器,服务器端的http服务软件(lnkHttpSvr.exe)根据请求返回数据(html,js,css,image...)
2).dll文件是在服务器端的电脑上运行的,由lnkHttpSvr解析执行,使用的是服务器端电脑的cup,disk等等资源。
3).html、js、css、image等文件是通过网络从服务端发送到客户端在客户端电脑上运行的,由浏览器软件解析执行,使用的是客户端电脑的cup,disk等等资源。
4).注意开发的时候我们工作的电脑既是服务端又是客户端。
2、基于HTTP协议,HTTP协议特点如下:
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
也通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高http服务器的吞吐率
无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。
缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。
支持客户/服务器模式。
lnkHttpSvr.exe应用WEB服务器
上图是lnkHttpSvr应用WEB服务器组成结构,它还支持如下的特性:
支持一个进程监听多个端口
支持多线程
支持多进程部署
支持根据域名或者端口自由指定运行根目录
支持静态文件,dll文件缓存到内存,提高IO性能
支持keep-alive、gzip压缩、自由设置ContentType等等
支持配置ssl
项目文件、DLL文件运行原理
请求文件按目录寻找加载执行,第一次从磁盘加载,后续从内存缓存中加载运行
DLL工程文件开发,按照?page=***&pcmd=***做命令动作路由映射,一个小模块3个类,6个文件做MVC模式规范编写
c***Proc类:用于参数page,pcmd作路由映射
c***Page类:用于控制输入、输出、视图界面以及其他控制调用
c***类:用于定义数据模型,与数据库交互,操作数据的增删改查,逻辑等
3 项目DLL开发及规范
cspProjectName | |---csp //待转换的 html 文件目录 | |---csp_c //待转换的 html 文件转换成 cpp 文件目录 |---cspPrj---|---entities //C***.h C***.cpp | |---proc_page //C***Proc.h C***Proc.cpp C***Page.h C***Page.cpp | |---cspMain.cpp //DLL 工程入口文件,导出函数/类声明,工程实例化 | |---appdomain.h //运用工程 cAppDomain 类头文件 | |---appdomain.cpp //将各个类以名称形式映射成 httpserver 的 url 参数page=名称,解析调用 | |---const.h | |----const.cpp //常量、全局变量、全局函数 | |---css //样式文件目录 | |---js //js 文件目录 | |---images //图片文件目录 |---_config.ini //该工程的配置文件工程配置文件_config.ini
[DEFAULT] supportEmail=zackqiu@link800.com redir=csp/cspTrack.dll?page=home IsLogErr = TRUE ErrLogFile=_cspTrackErr.log IsLogTSQL=TRUE IsDebug=TRUE IsLog=TRUE TRACER=FALSE TRACERFILE=_cspTrackTracer.log [AUTHENTICATION] dbConn=DATABASE=dbname;Server=127.0.0.1;Port=3306;DRIVER={MySQL ODBC 5.1 Driver}; UID=root;PWD=123456;OPTION=2049;charset=gbk;stmt=set names gbk [WEBPATH] workdir= cspTrack\csp\ [END]参看文档: link800软件开发-zbox项目工程DLL开发规范.pdf
4 项目DLL调试Debug及内存泄漏检测
F5编译运行
F9设置断点
F10是逐过程调试,单步执行,不进入调用的其它函数
F11是逐语句调试,单步执行,进入调用的其它函数
内存泄漏检测:
#ifdef _DEBUG #include "vld.h" #include "vldapi.h" #endif XPORT int Init(ckHttpServer *psvr, ckSession *pSn) { #ifdef _DEBUG VLDEnable(); #endif //..... }具体设置参看文档: 下载内存泄漏检测.pdf
5 常用SDK组件的使用
/*********************** *常用数据类型 ***********************/ /*********************** *POST\GET获取数据 ***********************/ //按名称获取GET/POST键对值 char* getRequest(char *field) ; char* getRequest(char *field, int &val); char* getRequest(char *field, double &val); char* getRequest(char *field, bool &val); char* getRequest(char *field, cString &val); char* getRequest(char *field, char **val); char* getRequest(char *field, char *valbuf, int buflen); char* getNextReq(char *fielddate, char *fieldtime, cTime &val, long &index, int format=CN_FMT, char *empty_date_str="1970-01-01"); //按索引获取GET/POST键对值 char* getRequest(int index, int &val); char* getRequest(int index, double &val); char* getRequest(int index, bool &val); char* getRequest(int index, cString &val); char* getRequest(int index, char **val); char* getRequest(int index) ; char* getRequest(int dtIndx, int tmIdx, cTime &val, int format=CN_FMT, char *empty_date_str="1970-01-01"); //获取POST全部数据 char* FormContent(); /*********************** *数据库操作 ***********************/ //cp_tranodbc.dll(数据库操作封装组建) // UPDATE/DELETE 使用executeNoQuery int CDefault::SetRouteStop(int pudo_addrid,int stop_id) { cString sql; int ret=1; sql &"UPDATE route_stop SET addr_id="&pudo_addrid&" WHERE stop_id="&stop_id&";"; ckOdbcConn *m_OdbcConn=OdbcConn(); m_OdbcConn->executeNoQuery(sql.GetBuf()); if (m_OdbcConn->ErrorNumber()!=0) { m_errMsg & "错误码=" & m_OdbcConn->ErrorNumber() & "; " & m_OdbcConn->ErrorMessage(); ret=0; } return ret; } // SELECT 使用executeQuery void CDefaultPage::QueryContact() { int ss_cont_id = 0; int ss_acct_id = 0; cString ss_cont_name; cString ss_cont_account; cString ss_displayContact; cString ss_cont_shortname; cString ss_acct_tel; cString sql; sql &"SELECT * FROM tblcontact;"; ckOdbcConn *m_OdbcConn=OdbcConn(); bool logflag = m_OdbcConn->GetLogFlag(); m_OdbcConn->SetLog(false); ckOdbcRecSet *rs = m_OdbcConn->executeQuery(sql.ToStr()); m_OdbcConn->SetLog(logflag); while (!rs->eof()) { ss_cont_id = rs->field_long("cont_id"); ss_acct_id = rs->field_long("cont_acctid"); ss_cont_name = rs->field_str("cont_name"); ss_cont_account = rs->field_str("cont_account"); ss_displayContact = rs->field_str("cont_person"); ss_cont_shortname= rs->field_str("cont_shortname"); ss_acct_tel = rs->field_str("tel"); rs->MoveNext(); } rs->Release(); }
6 常见犯错问题
6.2规范化问题(规范的写法避免理解不够造成坑)
6.3数据库问题
7 lnkHttpSvr服务器部署
一个进程监听多个端口
7.2 一台机器安装多个服务
多个服务多个进程
8 ini配置与Log日志记录
ini_httpConfig.ini
ini_tranodbc.ini
ini_httpClient.ini
8.2 Log日志
httpLog
odbclog
_SessionTimeOut.log
9 前端开发与说明
PubSrc前端库的介绍和使用
10 代码管理与版本控制
Trunk、Branches、Tags 区别:
Trunk:软件开发过程中的主线,开发时版本存放的目录,即在开发阶段的代码都提交到该目录上,保存了从版本库建立到当前的信息。
Branches:软件开发过程中的分支,发布版本存放的目录,即项目上线时发布的稳定版本存放在该目录中
tags:表示标签存放的目录,tags只可读,不可写
分支主要用于在不影响Trunk其它用户情况下进行一些关于新功能的探索性或实验性的开发,待新功能完善后它也可以合并到Trunk中。