以前我写过了,通过httpsys 提升windows 下,delphi 多层应用。随着delphi 10.2 对linux 的支持,很多人也想在linux 下

发布kbmmw 服务器,但是官方仅通过indy 支持 linux。刚好国内有大牛开源了Delphi 跨平台 Socket 通讯库.

通过这个可以直接让kbmmw 服务器高速的运行在在windows、linux、Mac 上。

delphi-cross-socket 的开源地址为:https://github.com/winddriver/Delphi-Cross-Socket

下面是官网的部分介绍。

Delphi 跨平台 Socket 通讯库作者: WiNDDRiVER(soulawing@gmail.com)
重要更新(2017.08.22)代码重构, 做了大量修改, 详见源码增加了几个新的 interface, 用法详见 demosICrossSocketICrossSslSocketICrossServerICrossSslServer特性针对不同平台使用不同的IO模型:IOCPWindowsKQUEUEFreeBSD(MacOSX, iOS...)EPOLLLinux(Linux, Android...)支持极高的并发Windows能跑10万以上的并发数, 需要修改注册表调整默认的最大端口数Mac做了初步测试, 测试环境为虚拟机中的 OSX 10.9.5, 即便修改了系统的句柄数限制, 最多也只能打开32000多个并发连接, 或许 OSX Server 版能支持更高的并发吧同时支持IPv4、IPv6零内存拷贝已通过测试WindowsOSXiOSAndroidLinux建议开发环境要发挥跨平台的完整功能请使用Delphi 10.2 Tokyo及以上的版本最低要求支持泛型和匿名函数的Delphi版本, 具体是从哪个版本开始支持泛型和匿名函数的我也不是太清楚

大家可以下载对应的源码,并使用delphi 测试它附带的例子程序。

今天简单说一下如何利用delphi-cross-socket 实现kbmmw 的跨平台开发。

首先我们做一个kbmmw transport.

声明如下。

unit kbmMWCrossScoketServerTransport;{.$define httpsyslog}interfaceusesClasses, Sysutils,kbmMWCustomTransport,kbmMWServer,kbmMWGlobal, variants,kbmMWHTTPUtils,kbmMWExceptions,{$ifdef httpsyslog}kbmMWLog,{$endif}Net.CrossSocket,{$IFDEF __SSL__}Net.CrossSslSocket,{$IFDEF POSIX}Net.CrossSslDemoCert,{$ENDIF}{$ENDIF}Net.SocketAPI;typeTProtServer = class(TkbmMWServer);TxalionTransport=class(TkbmMWCustomServerTransport);Txalioninfo=class(TkbmMWServerTransportInfo);Txalionserver = classprivateFServer:Tkbmmwserver;FTransport: TkbmMWCustomServerTransport;    FSocket: {$IFDEF __SSL__}TCrossSslSocket{$ELSE}TCrossSocket{$ENDIF};procedure OnReceived(Sender: TObject; AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer);
publicconstructor Create;destructor Destroy; override;end;TkbmMWCustomCrossScoketServerTransport = class(TkbmMWCustomServerTransport)private{ Private declarations }FCrossScoketServer: TxalionServer;Fhost:string;Fport:integer;// Fssl:boolean;Fversion:string;public// @excludeconstructor Create(AOwner:TComponent); override;// @excludedestructor Destroy; override;publicclass function IsSerializedTransport:boolean; override;class function IsConnectionlessTransport:boolean; override;procedure Listen; override;procedure Close; override;function IsListening:boolean; override;published{ 服务器 ip    例如   127.0.0.1}property Host:string read Fhost write Fhost;property Port:integer read Fport write Fport;Property Version:string read Fversion;end;{$IFDEF LEVEL16}[ComponentPlatformsAttribute({$IFDEF LEVEL26}pidLinux64 or{$ENDIF}{$IFDEF LEVEL23}pidiOSDevice64 or {$ENDIF}{$IFDEF LEVEL18}pidiOSSimulator or pidiOSDevice or {$ENDIF}{$IFDEF LEVEL19}pidAndroid or {$ENDIF}pidWin32 or pidWin64{$IFDEF LEVEL17} or pidOSX32{$ENDIF})]
{$ENDIF}TkbmMWCrossScoketServerTransport= class(TkbmMWCustomCrossScoketServerTransport)published{ Published declarations }property Crypt;property Compression;property StreamFormat;property VerifyTransfer;property TransportStateOptions;property FormatSettings;property Plugin;property Params;property StringConversion;property NodeID;property ClusterID;end;{$I CrossSocketversion.inc}{$ifdef httpsyslog}varfilelogmgr:TkbmMWLocalFileLogManager;{$endif}

实现部分如下:

implementationfunction kbmMWCrossScoketPutVerificationHeader(Size:integer):Tbytes;
vars:string;c:byte;i:integer;
constEOL=#10#13;
begins:=format('KBMMW X%0.8x ',[Size]); // 16 bytes.c:=0;for i:=KBMMW_STRINGCHAROFS to 16-KBMMW_STRINGCHARLENOFS doc:=c xor ord(s[i]);s:=s+format('X%0.2x'+EOL,[c]);    // 1+2+CR+LF = 5 bytes.
        setlength(result,length(s));for i := 1 to length(s) doresult[i-1]:=ord(s[i]);end;function kbmMWCrossScoketGetVerificationHeader(buff:pointer;len:integer):integer;
vars,s1:string;c,c1:byte;i:integer;pb:pbyte;
constSINVDATA = 'Invalid data';
beginResult:=0;                             // Satisfy compiler.c1:=0;s:='';trypb:=buff;for I := 0 to 20 dos:=s+chr((pb+i)^);// Extract checksum.trys1:=copy(s,17,3);c1:=strtoint(s1);exceptkbmMWRaiseException(KBMMW_ERR_TRANSPORT_INVALIDDATA,SINVDATA);end;// Calculate checksum.c:=0;for i:=KBMMW_STRINGCHAROFS to 16-KBMMW_STRINGCHARLENOFS doc:=c xor ord(s[i]);// Match?if c<>c1 thenexit;//kbmMWRaiseException(KBMMW_ERR_TRANSPORT_INVALIDDATA,SINVDATA);// Extract size.s1:=copy(s,7,9);tryResult:=strtoint(s1);exceptexit;// kbmMWRaiseException(KBMMW_ERR_TRANSPORT_INVALIDDATA,SINVDATA);end;exceptkbmMWDebugDumpMemory(mwdlAdvanced,mwdtTransport,kbmMWDebugWhere,'Exception during iocp verification',PByte(s),ByteLength(s));raise;end;
end;constructor Txalionserver.Create;
begininherited;FSocket :={$IFDEF __SSL__}TCrossSslSocket{$ELSE}TCrossSocket{$ENDIF}.Create(0);//FSocket.OnConnected := OnConnected;FSocket.OnReceived := OnReceived;
end;destructor Txalionserver.Destroy;
beginFSocket.Free;inherited;
end;procedure Txalionserver.OnReceived(Sender: TObject; AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer);varheadlen:integer;// 校验为 21 ,不校验为4
retl,i, j,inlen:integer;cStreamClass:TkbmMWCustomTransportStreamClass;OutStream:IkbmMWCustomResponseTransportStream;InStream:IkbmMWCustomRequestTransportStream;stamp:int64;AInfo:ikbmMWServerTransportInfo;//IkbmMWCustomTransportInfo;
   indata:pbyte;retdata:Tbytes;sr,query,spath,s:String;vt:word;bsize:tbytes;rethead:Tbytes;inStreamFormat:string;
begininStreamFormat:=TxalionTransport(FTransport).StreamFormat;if   (inStreamFormat<>'STANDARD')  thenbeginraise Exception.Create('Only support STANDARD StreamFormat.');end;//           beginif TxalionTransport(FTransport).VerifyTransfer thenbeginheadlen:=21;if kbmMWCrossScoketGetVerificationHeader(abuf,alen)<>(alen-headlen) then  //21为校验的头beginAConnection.SendBytes(Tencoding.UTF8.GetBytes('Invalid data'));exit;end;endelsebeginheadlen:=4;end;stamp:=TkbmMWTiming.GetTimeUS;aInfo:=TkbmMWServerTransportInfo.Create;cStreamClass:=TxalionTransport(FTransport).FControllerClass.CheckGetStreamClass(mwmtResponse);OutStream:=TkbmMWCustomResponseTransportStream(cStreamClass.Create(FTransport,AInfo));cStreamClass:=TxalionTransport(FTransport).FControllerClass.CheckGetStreamClass(mwmtRequest);InStream:=TkbmMWCustomRequestTransportStream(cStreamClass.Create(FTransport,AInfo));InStream.RemoteLocation:=AConnection.PeerAddr;// Client.PeerIP;
inlen:=alen-headlen;tryif inlen>0 thenbeginInStream.DataStream.Clear;InStream.DataStream.SetSize( inlen);indata:=pbyte(abuf);inc(indata,headlen);move(indata^,InStream.DataStream.Memory^,inlen);end;TProtServer(FServer).InternalServeStream(FTransport,InStream,OutStream);TProtServer(FServer).UpdateGlobalStats(InStream,OutStream,stamp);// Send response back.
retl:=OutStream.DataStream.Size;if TxalionTransport(FTransport).VerifyTransfer thenbeginrethead:=kbmMWCrossScoketPutVerificationHeader(retl);AConnection.SendBytes(rethead);//  client.Send(rethead[0],headlen);endelsebeginSetLength(bSize,4);bSize[3]:=(retl shr (8+8+8)) and 255;bSize[2]:=(retl shr (8+8)) and 255;bSize[1]:=(retl shr (8)) and 255;bSize[0]:=retl and 255;AConnection.SendBytes(bsize);//client.Send(bsize[0],4);end;setlength(retdata,retl);move(OutStream.DataStream.Memory^,retdata[0],retl);AConnection.SendBytes(retdata);excepton E: Exception dobegin{$ifdef httpsyslog}Log.Warn('Find error.'+e.Message );log.Warn('info:'+TkbmMWPlatformMarshal.memory2String(indata,inlen));{$endif}AConnection.SendBytes(Tencoding.UTF8.GetBytes(e.Message));//    client.Send(e.Message);end;end;end;
{ TkbmMWCustomhttpsysServerTransport }procedure TkbmMWCustomCrossScoketServerTransport.Close;
beginif state=mwtrstDisconnected then   exit;FCrossScoketServer.FSocket.DisconnectAll;//      Fiocpserver.fiocpServer.Stop;
      SetState(mwtrstDisconnected);
end;constructor TkbmMWCustomCrossScoketServerTransport.Create(AOwner: TComponent);
begininherited;FCrossScoketServer:= TxalionServer.Create;Fhost:='0.0.0.0';Fport:=3000;self.VerifyTransfer:=True;fversion:=sysversion;end;destructor TkbmMWCustomCrossScoketServerTransport.Destroy;
beginif FCrossScoketServer<>nil thenfreeandnil(FCrossScoketServer);inherited;
end;class function TkbmMWCustomCrossScoketServerTransport.IsConnectionlessTransport: boolean;
beginResult:=False;
end;function TkbmMWCustomCrossScoketServerTransport.IsListening: boolean;
beginResult:=(state=mwtrstListening);
end;class function TkbmMWCustomCrossScoketServerTransport.IsSerializedTransport: boolean;
beginResult:=true;
end;procedure TkbmMWCustomCrossScoketServerTransport.Listen;begininherited;if state=mwtrstListening then   exit;FCrossScoketserver.FServer:=server;FCrossScoketserver.FTransport:=self;FCrossScoketserver.FSocket.Listen(Fhost,Fport);SetState(mwtrstListening);end;{$ifdef httpsyslog}
initializationfilelogmgr:=TkbmMWLocalFileLogManager.Create('./kbmmwlog.txt'); // ,一个是日志文件filelogmgr.FileOptions:=[mwlfoDeleteOldLog];//:=true; // 删除老的日志文件filelogmgr.FlushInterval:=0; // 写文件时间间隔,0 为立即写文件Log.LogManager:=filelogmgr; //
     log.Info('Start logging!');{$endif}

把以上代码注册成控件并安装。

打开kbmmw 自带的例子 ,位置如图:

然后把原来的indy Transport 换成 我们新作的Transport.

服务端就ok了,我们可以编译运行,如图:

由于这是标准的tcp 传输协议,我们在客户段就直接使用indy 的代码(官方自带的)。

打开后,直接运行。

连接服务器,正常工作。windows 上没有任何问题。

在linux 下,我们可以参照这一篇 文章,把indy transport

换成 delphi-cross-socket transport 就可以了,其他的都不用动。就可以实现Linux 下运行的kbmmw server 了。

一下子直接跨三个平台。太爽了。

在此再次感谢开源delphi-cross-socket 的大牛兄弟。

转载于:https://www.cnblogs.com/xalion/p/8379518.html

利用Delphi-cross-socket 库提升kbmmw 跨平台开发相关推荐

  1. 利用Delphi编写Socket通信程序

    一.Delphi与Socket计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议.TCP是面向连接的,通信双方保持一条通路,好比目前的电话线,使用telnet登陆 ...

  2. 【iOS】利用CocoaPods创建私有库进行组件化开发

    之前使用CocoaPods管理过第三方库,前面也有翻译文章介绍过CocoaPods的配置方法,随着项目越来越大,很多公司会使用CocoaPods进行组件化开发,下面利用一个demo介绍一下. ###什 ...

  3. Delphi之对象库(Object Repository)

    对象库(Object Repository)是一种手段,通过这种手段,用户可以选择预定义的对象,并运用到自己的应用程序中,用对象库能做以下的工作: 选择一个预定义的应用程序.窗体或对话框,用于用户的应 ...

  4. Windows下Socket库的初始化和关闭

    文章目录 1 Windows下Socket库的初始化和关闭 1 Windows下Socket库的初始化和关闭 windows下使用Socket比较特殊,使用前我们需要对socket库进行初始化,使用完 ...

  5. Delphi的Socket编程要分几步?

    Delphi的Socket编程要分几步? 2008-12-20 02:03:24 标签:Delphi Socket 编程 [推送到技术圈] ClientSocket 和ServerSocket 几个重 ...

  6. Python学习教程(Python学习路线):如何正确使用Pandas库提升项目的运行速度?...

    Python学习教程:如何正确使用Pandas库提升项目的运行速度? 如果你从事大数据工作,用Python的Pandas库时会发现很多惊喜.Pandas在数据科学和分析领域扮演越来越重要的角色,尤其是 ...

  7. python socket通信 recv 丢包_用clumsy模拟丢包测试socket库的失败重传

    用python的socket库写了通信小程序,现在我需要通过软件模拟出在网络极差的情况下,socket底层解决丢包问题的能力怎么样,我一开始想的是分别在linux和windowns下分别测试,后来一想 ...

  8. 用python画玫瑰花教程-利用Python的turtle库绘制玫瑰教程

    用Python的turtle库绘图是很简单的,闲来无事就画了一个玫瑰花,下面奉上源码.... 源码: ''' Created on Nov 18, 2017 @author: QiZhao ''' i ...

  9. 利用Delphi的File Of Type创建并管理属于你自己的数据库

    http://www.360doc.com/content/16/1128/19/28222077_610249962.shtml 利用Delphi的File Of Type创建并管理属于你自己的数据 ...

最新文章

  1. KVell 单机k/v引擎:用最少的CPU 来调度Nvme的极致性能
  2. java时间转换 YYYY yyyy
  3. Linux内核探讨-- 第五章
  4. python 画log曲线
  5. php挖洞提权,记一次渗透挖洞提权实战
  6. Cortex‐M3-总线接口
  7. rxjs of操作符生成的Observable对象的执行详细分析
  8. UVA10972 - RevolC FaeLoN(双连通分量)
  9. python loadtxt_Python 数据科学入门2:Matplotlib
  10. cascade=CascadeType.ALL的深坑
  11. mysql并发参数查看_MySQL Innodb 并发涉及参数
  12. uboot网络调试方法
  13. Java代码生成器简介、原理、开发流程和Demo
  14. AppScan安装包及详细安装教程(带图)
  15. node.js连接数据库写接口
  16. 弱监督论文解读:CADN- 用于表面缺陷检测的基于弱监督学习的分类感知对象检测网络
  17. vue 项目 build 之后dist文件下的index.html不显示内容,并且报 Failed to load resource: net::ERR_FILE_NOT_FOUND 错误
  18. Delta RPMs disabled because /usr/bin/applydeltarpm not installed解决办法
  19. php如何截取出视频中的指定帧作为图片
  20. CCS2020论文泛读记录

热门文章

  1. 面向程序员的GPGPU技术系列(1) 为什么要理解GPU体系结构?
  2. dom4j获取指定节点值_XML解析之DOM4j以及XPATH技术
  3. cv2.error: opencv(4.4.0)_【OpenCV 4开发详解】图像连通域分析
  4. mysql 5.7 多条件 in_5分钟了解MySQL5.7对in用法有什么黑科技
  5. python 函数中参数的传递方式(三分钟读懂)
  6. linux下实现对多个文件去重软件,Linux下大文件的排序和去重复
  7. pytorch学习笔记(二十):Padding-And-Strides
  8. AcWing1069.凸多边形的划分(区间DP)题解
  9. 5-3 面向可维护性的构造技术
  10. LightGCN: Simplifying and Powering Graph Convolution Network for Recommendation 论文笔记