[DIOCP3/MyBean/QDAC开源项目] DataModule-DB例子基于MyBean的插件实例<三层数据库方案>

【说明】

这个例子答应大家很久了,一直没有时间弄,现在正式结合MyBean插件可以很方便的在客户端共享操作连接,执行数据库的各项工作,屏蔽了底层的通信解码器编码等工作,直接传递Variant,给了开发者足够的领活和自由。

【服务端使用技术】

diocp3:担当底层的通信任务。

qworker/iocpTask:担当业务逻辑的处理工作,diocp3接受数据解码后用qworker/iocpTask将数据包投递出来,这样不用占用通信线程。

qmsgpack:负责将传递的将variant数据打包到流,从流中解码成variant

dataModule:对应连接的对象,方便进行开发。

【客户端】

myBean:制作基于MyBean框架的插件,可以在MyBean的框架模块中直接使用。

RawTcpClient:用于和服务端进行通信,阻塞的tcp客户端,类似IdTcpClient的精简版本,操作容易。

【DEMO使用】

说 明:客户端依赖diocp_bean.dll插件与服务器进行数据交换,DIOCP_DBDEMO.dll是演示窗体插件的宿主。

存放路径:MyBean\samples\diocp-DBDEMO

启动服务:SERVER_EXE\diocp3Server.exe  <点击start按钮启动服务>

服务器是基于DIOCP3的。可以在DIOCP3项目中找到源码[diocp3\samples\socket-Coder\DataModuleDEMO]

启动客户端:打开 [simpleConsole.exe], 依次点击下面的按钮就可以看到效果了

【DEMO说明】

服务端处理:

服务端基于DIOCP3通信,该DEMO做了简单的封装,使用户可以专注于逻辑的实现,和客户端交互使用variant类型进行。

dmMain,是和客户端连接想对应的一个对象[和客户端的连接是一对一的关系]。

我在里面稍微做了下逻辑处理的演示:

function TdmMain.Execute(pvCmdIndex: Integer; var vData: OleVariant): Boolean;
begin
  case pvCmdIndex of
    0:
      begin
        // 返回服务端时间给客户端
        vData := Now();
        Result := true;
      end;
    1:  // 查询数据
      begin
        // vData 认为是传入的SQL语句
        //   执行后, vData为查询的数据,可以用于对ClientData.Data的赋值

        qryMain.Close;
        qryMain.SQL.Clear;
        qryMain.SQL.Add(vData);
        qryMain.Open;

        vData := dspMain.Data;
        Result := true;
        qryMain.Close;
      end;
    2:
      begin
        // vData 为执行的语句
        conMain.BeginTrans;
        try
          qryMain.Close;
          qryMain.SQL.Clear;
          qryMain.SQL.Add(vData);
          qryMain.ExecSQL;
          conMain.CommitTrans;

          VarClear(vData);

          Result := true;

        except
          conMain.RollbackTrans;
          raise;
        end;
      end;
  end;
end;

vData,是客户端传递过来的参数,也是返回给客户端的数据。vData是OleVariant可以容纳任何的数据<配合qmsgPack可以达到任何的数据格式要求>, 如果还达不到你的格式要求,你可以在MyClientContext的dataReceived函数做些修改,下面代码的处理过程依次是:

解压收到的数据->QmsgPack解包->取出客户端传入的参数->调用dmMain.Execute处理逻辑->qmsgPack编码数据->压缩数据->回传数据到客户端

procedure TMyClientContext.dataReceived(const pvDataObject: TObject);
var
  lvMsgPack:TQMsgPack;
  lvStream :TStream;
  lvStream2:TMemoryStream;
  vData:OleVariant;
  lvResult:Boolean;
begin
  lvMsgPack := TQMsgPack.Create;
  try
    try
      if FdmMain = nil then FdmMain := TdmMain.Create(nil);

      lvStream := TStream(pvDataObject);
      lvStream.Position := 0;

      // upZip
      TZipTools.unCompressStreamEX(lvStream);

      lvStream.Position := 0;

      // unpack
      lvMsgPack.LoadFromStream(lvStream);

      // get param
      vData := lvMsgPack.ForcePath(‘cmd.data‘).AsVariant;

      // invoke dataModule function
      lvResult := FdmMain.Execute(lvMsgPack.ForcePath(‘cmd.index‘).AsInteger, vData);

      // write result info
      lvMsgPack.Clear;
      lvMsgPack.ForcePath(‘__result.result‘).AsBoolean := lvResult;
      lvMsgPack.ForcePath(‘__result.data‘).AsVariant := vData;
    except
      on E:Exception do
      begin
        lvMsgPack.Clear;
        lvMsgPack.ForcePath(‘__result.result‘).AsBoolean := false;
        lvMsgPack.ForcePath(‘__result.msg‘).AsString := e.Message;
      end;
    end;

    lvStream.Size := 0;
    lvMsgPack.SaveToStream(lvStream);

    lvStream.Position := 0;

    // zipStream
    TZipTools.compressStreamEX(lvStream);
    lvStream.Position := 0;

    // send to client
    self.writeObject(lvStream);
  finally
    lvMsgPack.Free;
  end;

end;

客户端处理:

编译的 DLL 放到和EXE同一个目录下面就可以进行自动加载。

客户端diocp_bean工程中

library diocp_bean;

uses
  SysUtils,
  Classes,
  mybean.core.beanFactoryForNoVcl,
  uRemoteServerDIOCPImpl in ‘Service\uRemoteServerDIOCPImpl.pas‘;

{$R *.res}

begin
  beanFactory.RegisterBean(‘diocpRemoteSvr‘, TRemoteServerDIOCPImpl).Singleton := true;
end.

注册的diocpRemoteSvr插件实现了IRemoteServer接口和IRemoteServerConnector接口,而且该插件为单件模式。其他任何地方调用都只会产生一个连接实例。

type
  IRemoteServer = interface(IInterface)
    [‘{20B5F070-461C-41F4-AA0C-E500A36E18E4}‘]

    /// <summary>
    ///   执行远程动作
    /// </summary>
    function Execute(pvCmdIndex: Integer; var vData: OleVariant): Boolean; stdcall;
  end;

  IRemoteServerConnector = interface(IInterface)
    [‘{65931F56-07BA-42F8-BD5C-7409053F5B2C}‘]
    procedure setHost(pvHost: PAnsiChar);
    procedure setPort(pvPort:Integer);
    procedure open;
  end;

演示操作窗体:<服务端是13K的成语记录>

相应按钮代码:

constructor TfrmMain.Create(AOwner: TComponent);
begin
  inherited;
  // 通过注册的插件ID获取单实例的远程连接操作接口
  FRemoteSvr := TMyBeanFactoryTools.getBean(‘diocpRemoteSvr‘) as IRemoteServer;
end;

procedure TfrmMain.btnConnectClick(Sender: TObject);
begin
  // 打开远程连接,如果打开过可以不用打开,其他插件中可以直接使用
  (FRemoteSvr as IRemoteServerConnector).setHost(PAnsiChar(AnsiString(edtHost.Text)));
  (FRemoteSvr as IRemoteServerConnector).setPort(StrToInt(edtPort.Text));
  (FRemoteSvr as IRemoteServerConnector).open;
  ShowMessage(‘open succ!‘);
end;

procedure TfrmMain.btnOpenClick(Sender: TObject);
var
  vData:OleVariant;
  l : Cardinal;
begin
  vData := mmoSQL.Lines.Text;

  l := GetTickCount;

  // 在远程打开SQL
  if FRemoteSvr.Execute(1, vData) then
  begin
    self.cdsMain.Data := vData;
    Self.Caption := Format(‘query: count:%d, time:%d‘,
      [self.cdsMain.RecordCount, GetTickCount - l]);
  end;
end;

PS: 其他功能大家自己去实现,该文章写了好几个中午,希望对大家有用。

由于qdac开源项目 >=D2007,所以D7下面不能编译服务端,和diocp_bean.项目(你可以在D2007中编译好diocp_bean和服务端工程,其他插件可以在d7中完成)

-----------------------------------------------------------------------------------------------------

MyBean 轻量级配置开源框架 开源地址

https://git.oschina.net/ymofen/delphi-framework-MyBean

DIOCP3开源地址

https://github.com/ymofen/diocp3

qdac项目信息

官方网站:http://www.qdac.cc

官方QQ群:250530692

QDAC项目网址:http://sourceforge.net/p/qdac3

在线源码浏览:http://sourceforge.net/p/qdac3/code/HEAD/tree/

SVN检出地址:

http://svn.code.sf.net/p/qdac3/code/
svn://svn.code.sf.net/p/qdac3/code/

时间: 2024-10-03 14:07:07

[DIOCP3/MyBean/QDAC开源项目] DataModule-DB例子基于MyBean的插件实例<三层数据库方案>的相关文章

开源项目kcws代码分析--基于深度学习的分词技术

http://blog.csdn.net/pirage/article/details/53424544 分词原理 本小节内容参考待字闺中的两篇博文: 97.5%准确率的深度学习中文分词(字嵌入+Bi-LSTM+CRF) 如何深度理解Koth的深度分词? 简单的说,kcws的分词原理就是: 对语料进行处理,使用word2vec对语料的字进行嵌入,每个字特征为50维. 得到字嵌入后,用字嵌入特征喂给双向LSTM, 对输出的隐层加一个线性层,然后加一个CRF就得到本文实现的模型. 于最优化方法,文本

DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了

[概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天晚上,DEMO基本成型,今天再加入了QWorkers来做逻辑处理进程,进一步使得逻辑处理进程更加方便和高效.今天特意写篇blog来记录我的心得与大家分享. [功能实现说明] 沿用上次的草图 目前DEMO图上的功能都已经实现.下面谈谈各部分的实现. 通信服务, 由DIOCP实现,担当与客户端的通信工作

Delphi国内优秀网站及开源项目

Delphi编程技巧大全     http://www.delphitop.com/ Delphi盒子 www.2ccc.com 2Pascal-新时代的Pascal http://www.2pascal.com WeDelphi http://www.WeDelphi.com 新大富翁论坛 http://www.dfwlt.com/forum.php 万一的博客:http://www.cnblogs.com/del/ 原Delphi窖洞洞主博客:http://www.cnblogs.com/x

[转]Android开源项目收藏分享

转自:http://blog.csdn.net/dianyueneo/article/details/40683285 Android开源项目分类汇总 如果你也对开源实现库的实现原理感兴趣,欢迎 Star 和 Fork 14884(入群理由必须填写群简介问题答案)4489 63224677(三群已满) 欢迎大家推荐好的Android开源项目,可直接Star.Fork :) 对你有帮助的话,顺手去知乎点个赞吧: 目前包括: ActionBar.ViewPager.GridView.Progress

分布式锁实现思路及开源项目集成到springmvc并使用

分布式锁顾名思义就是在分布式系统下的锁,而使用锁的唯一目的就是为了防止多个请求同时对某一个资源进行竞争性读写 在使用多线程时,为了让某一资源某一时刻只能有一个操作者,经常使用synchronized,这点大家都很熟悉 那什么时候使用分布式锁? 当一套项目只部署一套的时候,使用synchronized就可以了,但是当同一套项目部署了多套,即进行分布式部署时, 假设部署了同样的A,B,C三套系统,系统里面有一个操作同一时刻只允许一个用户进行操作,如上所说,只部署一套时,用synchronized限定

DIOCP开源项目-DIOCP3 大文件的传输DEMO&lt;断点续传&gt;

首先该DEMO在StreamCoder上面做的改动,期间导致StreamCoderDEMO经常出现问题,导致大家运行的时候,频频出现问题,表示道歉. 以下是测试的结果,从服务器下载传输了一个3G左右的文件(Win7.iso).传输后用Hash工具做了个测试,是一样的.后面贴出了两个文件的贴图. 下面是客户端接受到文件的hash截图 下面是服务端源文件的hash截图 协议和功能 该DEMO由客户端请求服务端位与Files下面的文件,第一次请求文件信息(文件大小),请求到文件后,请求下载文件数据,收

DIOCP开源项目-DIOCP3的重生和稳定版本发布

DIOCP3的重生 从开始写DIOCP到现在已经有一年多的时间了,最近两个月以来一直有个想法做个 30 * 24 稳定的企业服务端架构,让程序员专注于逻辑实现就好.虽然DIOCP到现在通讯层已经很稳定了,但是要做如果做这种架构,发现还有诸多不便.于是,有了重写DIOCP的想法. 关于开源服务器的选用: 前段时间大部分代码已经编写完成,于是需要给diocp3安个家,google显然不行了,老是被墙.然后准备选用http://sourceforge.net/,发现我的qq email老是收不到验证邮

DIOCP开源项目-DIOCP3直接发送对象,帮你处理粘包问题

该DEMO演示,如何在客户端与服务端之间直接传递TStream对象,让你专注于处理数据逻辑,可以忽略处理网络传输间粘包的问题. 上面由服务端向所有的客户端推送一个消息TMemoryStream对象(该对象为字符串数据). 代码解释: procedure TfrmMain.actPushMsgExecute(Sender: TObject); var lvList:TList; i: Integer; lvStream:TMemoryStream; s:AnsiString; begin lvLi

DIOCP开源项目-DIOCP3的ECHO测试&lt;贴图&gt;

星期六开了测试台测试机子.星期天休息,今天早上来接两个图 开了2个客户端,一个qsl的echo client,一个是楠楠的dbiocp回调客户端.建立13240个连接 今天来后,机子很卡,后来发现是楠楠的dbiocp导致的.难怪,速率才14M /s,刚1个小时能达到 90M/S,关掉后,和qsl的客户端继续很正常. 唯一的缺陷是,Integer溢出了,导致统计数据出现了负数.qsl的客户端一样也是这个问题,实际使用倒是可以忽略. 内存占用<设定的WSARecv的内存块大小为1024>,内存占用