您当前位置:闸机 >> 相关资源 >> 开发相关 >> 浏览文章      |关键词:

顺极传输中间件DLL调用代码及UML

2011/7/19 17:48:44 本站原创 开发部 【字体:

开发UML文档

顺极科技闸机、客户端连接服务器将使用新的中间件DLL,本中间件DLL为TCP传输方式,可以传送命令,如开门、关门、文字显示等,也可以传输文件,如图片数据,我公司闸机的指纹数据和图片使用DLL动态库传输,数据是按实际大小传输的,传输性能高,中间件的传输是内存流的传输,是底层传输中间件,与语言的编码无关。目前调用已经翻译成delphi工程,并做了相关DEMO,我们将择时公开本DEMO源码,以供大家二次开发参考。

//DLL相关代码,DLL为VC制作

unit importf;

interface

const sjdllname='sj_transdata_tp.dll';
const  __SHUN_JI_WWW='www.HeroGod.com\0';


function sj_sendto(Data:PChar;len:Integer;RemIp:PChar;iplen:Integer=0;
       nRemotePort:Integer=0):Integer; cdecl;
function sj_startrev(confirms:PChar;maxBufSize:Integer=1024*40;{*如果为0,则为40Kb,如果只是传命令,无图片传输,只需1k*/} nPort:Integer=0{/*监听的端口,0为默认的5101*/}):Integer cdecl;//开始接收
function sj_havedata(timeout:Integer=500):Integer;cdecl;//询问是否有数据来到,不停的询问
function sj_readdata(Data:PChar;dataLen:PInteger;ip:PChar;iplen:PInteger):Integer;cdecl;//如果有数据,则接收数据,得到数据的长度和IP地址
function sj_stoprev():Integer;cdecl;//停止接收数据


implementation
 function sj_sendto;cdecl;external sjdllname;
 function sj_startrev;cdecl; external sjdllname;
 function sj_stoprev;cdecl;external sjdllname;
 function sj_havedata;cdecl;external sjdllname;
 function sj_readdata;cdecl;external sjdllname;
end.


{#define __SHUN_JI_WWW "www.HeroGod.com\0"

/************************************************************************/
/*顺极科技TCP传送中间件,本中间件内部为多线程,接收和发送都是按实际字节传输
DLL为unicode环境,但函数只关心字节本身,不涉及编码问题
接收时,最多允许1000个客户端,这时要注意传输量和客户的总流量
本中间件可传输任意大小的数据包,默认为40KB
*/
/************************************************************************/

 

/* 开始接收数据,本函数只用于接收的开始,实际上启动TCP监听
confirms:确认字符
 必须为www.HeroGod.com,否则会失败
maxBufSize:缓存大小
 缓存大小在开始后不能改变,应比实际传输的最大值大
nPort:默认端口
 TCP监听的端口,无特殊情况,应使用默认值
*/
int sj_startrev(char* confirms=__SHUN_JI_WWW,int maxBufSize=1024*40,/*如果为0,则为40Kb,如果只是传命令,无图片传输,只需1k*/int nPort=0/*监听的端口,0为默认的5101*/);//开始接收


/*
停止接收数据,在开始后用于停止
注意,顺序不能错
*/
int sj_stoprev();//停止接收数据

/*
询问内部是否有数据
应在开始接收后,不停的询问是否有数据到来,调用为阻塞式
 timeout:如果没有数据,等待的超时时间
 超时只在数据没有到来时起作用,数据到来时,立即返回,因此设置较长时间不会影响数据接收
 如果在多线程中调用,可以将超时设置长一些,以节省资源
 询问到一次数据后,必须读取,否则再次询问将返回0
 如果有数据,返回的是数据的长度
*/
int sj_havedata(int timeout=500);//询问是否有数据来到,不停的询问

/*
读取数据
在sj_havedata返回有数据后,应立即调用此函数读取数据,否则数据可能会被新来的数据覆盖
 Data:接收到的原始数据,该数据应先分配好,接收频繁的话,应事先分配传输时的最大值的内存,最好是全局变量,以节省资源
 datalen:接收到的数据长度
 ip:数据来源的IP地址,也应事先分配好ip的最大值,比如24字节的数组
 iplen:ip地址的字符串的总长度.
*/
int sj_readdata(char *Data,int& dataLen,char *ip,int& iplen);//如果有数据,则接收数据,得到数据的长度和IP地址

 


/*
发送数据,该函数是独立的,如果只是发送数据,可以不调用以上函数而直接发送数据
 Data:要发送的数据缓存
 len:要发送的长度
 RemIp:目标IP地址,要在IP地址的有效字符串之后加'\0'
 iplen:目标地址长度,为RemIp带'\0'的总长度,如果是0,则RemIp必须为'\0'结束
 程序内部会执行:RemIp[iplen]='\0';
 nRemotePort:远程端口,可以使用0作为默认端口,默认为5101
*/
int sj_sendto(char* Data,int len,char* RemIp,int iplen=0,int nRemotePort=0/*要发送的远程的端口,0为默认的5101端口*/);//发送数据
 } 

 

//接收数据的线程,收到数据后,通过消息发送到主窗体

unit ReadThread;

interface

uses
  Windows,Classes,Messages;

  const USRMSG_RECVDATA= WM_USER+101;
  const USRMSG_CLOSETHD=WM_USER+102;

type TRevDataSUT=record
    mData:array[0..1024*40] of Char;
    nDatalen:Integer;
    cIp:array[0..23] of Char;
    nIpLen:Integer;
end;
type TPRevDataSUT=^TRevDataSUT;

type
  TReadThd = class(TThread)
  private
    { Private declarations }
    m_hWnd:HWND;
  protected
    procedure Execute; override;
  public
    bRunning:Boolean;
   constructor Create(hwnd:HWND);

  end;

implementation

uses importf;

 

constructor TReadThd.Create(hwnd:HWND);
begin
  bRunning:=True;
  FreeOnTerminate:=True;
  m_hWnd:=hwnd;
  inherited Create(False);   
end;

procedure TReadThd.Execute;
var bHav:Boolean;
    vRevDataStu:TRevDataSUT;
begin
  { Place thread code here }
  while bRunning do
  begin
   bHav:= sj_havedata(500)=1;
   if bHav then
   begin
    bHav:= sj_readdata(vRevDataStu.mData,@vRevDataStu.nDataLen,vRevDataStu.cIp,@vRevDataStu.nIpLen)=1;
    PostMessage(m_hWnd,USRMSG_RECVDATA,Integer(@vRevDataStu),0);
   
   end;
  end;
  PostMessage(m_hWnd,USRMSG_CLOSETHD,0,0);
 
end;

end.

 主窗口,比较简单,应该能看懂吧

unit mainf;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Spin,ReadThread;

type
  TFrmMain = class(TForm)
    grp1: TGroupBox;
    lbl1: TLabel;
    se_lsnport: TSpinEdit;
    btn_start: TButton;
    btn_stop: TButton;
    mmo_recv: TMemo;
    lbl2: TLabel;
    grp2: TGroupBox;
    lbl3: TLabel;
    se_rm_port: TSpinEdit;
    lbl4: TLabel;
    edt_rm_ip: TEdit;
    mmo_send: TMemo;
    btn_send: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btn_sendClick(Sender: TObject);
    procedure btn_startClick(Sender: TObject);
    procedure btn_stopClick(Sender: TObject);
  private
    { Private declarations }
    vReadThd:TReadThd;
    procedure RevDataFun(var mmsg:TMessage);message USRMSG_RECVDATA;
     procedure RevStopFun(var mmsg:TMessage);message USRMSG_CLOSETHD;
  public
    { Public declarations }
  end;

var
  FrmMain: TFrmMain;

implementation

{$R *.dfm}

uses importf;

procedure TFrmMain.btn_sendClick(Sender: TObject);
var nRet:Integer;
  sendstr:string;
  sendlen:Integer;
  ipstr:string;
  iplen:Integer;
begin
  sendstr:= mmo_send.Text;
 sendlen:= Length(sendstr);
 ipstr:=edt_rm_ip.Text;
 iplen:=Length(ipstr);
  nRet:= sj_sendto(@sendstr[1],sendlen,@ipstr[1],iplen,se_rm_port.Value);
  if nRet<>1 then
  begin
    ShowMessage('发送出错');
    Exit;
  end;
  mmo_send.Clear;

end;

procedure TFrmMain.btn_startClick(Sender: TObject);
var rRet:Integer;
begin
  rRet:=sj_startrev(__SHUN_JI_WWW,1024*40,0) ;
  if rRet=0 then
  begin
    ShowMessage('开始出错');
    Exit;
  end;
  //开线程
  vReadThd:=TReadThd.Create(Handle);
  btn_start.Enabled:=False;
  btn_stop.Enabled:=True;

end;

procedure TFrmMain.btn_stopClick(Sender: TObject);
begin
  vReadThd.bRunning:=False;
  WaitForSingleObject(vReadThd.Handle,INFINITE);
  sj_stoprev();
  btn_start.Enabled:=True;
  btn_stop.Enabled:=False;
end;

procedure TFrmMain.FormCreate(Sender: TObject);
begin
  edt_rm_ip.Text:='127.0.0.1';
  se_rm_port.Value:=5101;
  se_lsnport.Value:=5101;
  btn_stop.Enabled:=False;
  mmo_recv.Clear;
  mmo_send.Clear;
end;

procedure TFrmMain.RevDataFun(var mmsg: TMessage);
var pData:TPRevDataSUT;
  str1,str2:string;
begin
  pData:=TPRevDataSUT( mmsg.WParam);
  str1:=StringOfChar(Chr(0),pData.nDatalen);
  CopyMemory(@str1[1],@pData.mData,pData.nDatalen);
  str2:=StringOfChar(Chr(0),pData.nIpLen);
  CopyMemory(@str2[1],@pData.cIp,pData.nIpLen);
  mmo_recv.Lines.Insert(0,Format('来自:%s'#13#10'  数据为:%s'#13#10#13#10,[str2,str1]));
  str1:='';
  str2:='';
 
end;

procedure TFrmMain.RevStopFun(var mmsg: TMessage);
begin
  mmo_recv.Lines.Insert(0,'已经停止'#13#10);
end;

end.

相关栏目:

网友评论: