如何分离通信物理接口和应用程序

来源:百度文库 编辑:神马文学网 时间:2024/05/01 10:34:24
一、   我们在使用通信控件时,为什么需要隔离物理传输和应用程序?我们常用的数据控件如:串口,TCP/IP,UDP等,封装了Windows API去处理不同的传输特性,例如:不同的属性,不同的错误,不同的发送和接收数据流程,如果我们在应用程序中,直接使用此类控件,就会造成应用程序依赖于这些物理特性,而导致我们要换用不同的物理传输时(例如:从串口换到TCP/IP),应用程序进行大量修改。所以,为了避免这种情况,我们需要找到一种办法,去隔离物理传输对应用程序的影响。 二、   我们如何来实现隔离物理传输对应用程序的影响  2.1设计思路     实现我们看一下,应用程序关心什么?它关心收到数据和发送数据,以及各种状态(例如:发送前,发送后,记录Log和错误信息等。所以,我们的设计思路是,提供一个通用的中间类,来隔离物理传输和应用程序。 应用程序Application
 
中间类TwyqDataLink
 
物理传输控件(Serial,TCP/IP,UDP等)
 
中间类的后代
 
     
                    例如:对TCP/IP我们定义类TwyqTCPServer:TwyqDataLink和TwyqTCPClient:TwyqDataLink,对串口,我们使用TwyqSerial:TwyqDataLink,在应用程序中,不管我们使用串口或TCP/IP,我们使用MyDataLink:TwyqDataLink; 如果使用串口,则MyDataLink=TwyqSerial的实例,如果使用TCP/IP,则MyDataLink=TwyqTCPSevrer的实例或MyDataLink=TwyqTCPClient的实例。这样,应用程序中,使用MyDataLink的代码,就不会被具体的物理控件所影响。 2.2 具体实现 2.2.1我们可以定义如下的abstract的数据链路类:TLinkEvent = procedure (Sender: TObject;MSG:String) of object; TwyqDataLink = class (TComponent)  private    FONAfterSend: TLinkEvent;    FONBeforeSend: TLinkEvent;    FONConnect: TNotifyEvent;    FONError: TLinkEvent;    FONLog: TLinkEvent;    FONReceive: TLinkEvent;    FONSyncReceive: TLinkEvent;  protected    function GetActive: Boolean; virtual; abstract;    procedure SetActive(Value: Boolean); virtual; abstract;  public    function Close: Boolean; virtual; abstract;    function Open: Boolean; virtual; abstract;    function Read(Var Text:String;Count:cardinal;var rCount:cardinal): Boolean;             virtual; abstract;    function Send(CMD:String;Var rCount:cardinal): Boolean; virtual; abstract;    property Active: Boolean read GetActive write SetActive;  published    property ONAfterSend: TLinkEvent read FONAfterSend write FONAfterSend;    property ONBeforeSend: TLinkEvent read FONBeforeSend write FONBeforeSend;    property ONConnect: TNotifyEvent read FONConnect write FONConnect;    property ONError: TLinkEvent read FONError write FONError;    property ONLog: TLinkEvent read FONLog write FONLog;    property ONReceive: TLinkEvent read FONReceive write FONReceive;    property ONSyncReceive: TLinkEvent read FONSyncReceive write FONSyncReceive;  end; 2.2.2 我们再来看一下实现TCPClient的类定义TBufferKind=(skNormal,skBufferIsOne,skNoBuffer);TwyqClientSocket = class (TwyqDataLink)  private    FPort: TClientSocket;    FWaitOpenTimer:integer;    FOnConnecting:TSocketNotifyEvent;    FOnError:TSocketErrorEvent;    FAsyncConnect:Boolean;    FBufferKind:TBufferKind;    FIsThreadMode:Boolean;    FBuf:TSyncBuf;    FThread:TwyqMsgToThread;    procedure FSetPort(Value: TClientSocket);  protected    function GetActive: Boolean; override;    procedure impONRead(Sender:TObject;Socket: TCustomWinSocket);    procedure SetActive(Value: Boolean); override;    procedure csError(Sender: TObject; Socket: TCustomWinSocket;  ErrorEvent: TErrorEvent; var ErrorCode: Integer);    Procedure csConnecting(Sender:TObject;Socket:TCustomWinSocket);  public    property WaitOpenTimer:Integer read FWaitOpenTimer write FWaitOpenTimer;    function Close: Boolean; override;    function Open: Boolean; override;    function Read(Var Text:String;Count:cardinal;var rCount:cardinal): Boolean;            override;    function Send(CMD:String;Var rCount:cardinal): Boolean; override;    constructor Create(owner:TComponent);Override;    destructor Destroy;override;  published    Property BufferKind:TBufferKind read FBufferKind write FBufferKind;    property Socket: TClientSocket read FPort write FSetPort;    Property IsThreadMode:Boolean read FIsThreadMode write FIsThreadMode;  end; 2.2.3        上面代码中,我们看到两个新类TSyncBuf和TwyqMessgaeToThread和一个IsThreadMode的属性,下面解释一下,它们用于什么: a)      如果IsThreadMode=True,那么,我们将会在创建的TwyqMessgaeToThread县城中,去调用ONReceive事件,否则,直接调用ONReceive事件。 b)      TSyncBuf是为了实现一个线程安全的先进先出的String队列,它的定义如下:TSyncBuf = class (TPersistent)  private    FCriticalSection: TRTLCriticalSection;    FStringList: TStringList;  protected    procedure lock;    procedure unlock;  public    constructor Create;    destructor Destroy; override;    procedure Inbuf(Const S:string);    Procedure InMultiBuf(Consts:Array of String);    function OutBuf: string;    Function IsNotEmpty:Boolean;  end; c)      TwyqMessgaeToThread的定义如下:TwyqMsgToThread=class(TThread) Private   FBuf:TSyncBuf;   FReceiver:TwyqDataLink; protected  procedure Execute;override; public  Constructor Create(Receiver:TwyqDataLink;buf:TsyncBuf); end;