利用完成端口开发的服务端,其整体程序如下:
unit Servermanage;
//对通信的管理
interface
uses
SysUtils, Classes,Variants, IOCPComp, SyncObjs, comms,Messages;Type TServerManage=Class
private
FLock: TCriticalSection; //锁定标志
FServerSocket: TServerSocket; //服务 FServerActive: Boolean; //服务激活标志 protected
function OnClientRead(ASocket: TCustomSocket; AData: Pointer;
ACount: Integer): Integer;
procedure OnClientError(ASocket: TCustomSocket; ErrorEvent: TErrorEvent;
var ErrCode: Integer);
procedure OnClientEvent(ASocket: TCustomSocket;
SocketEvent: TSocketEvent);
procedure SetServerActive(const Value: Boolean); function GetLoginCount:Integer;//返回登录的总计人数
public
procedure initPort;
procedure StartServer;
procedure StopServer;
procedure RefreshServer;//刷新服务 constructor Create(AOwner: TComponent);
destructor Destroy; override; published
property ServerActive:Boolean read FServerActive write SetServerActive; Property LoginCount:integer read GetLoginCount; End;
implementation
constructor TServerManage.Create(AOwner: TComponent);
begin
inherited Create; FLock := TCriticalSection.Create; FServerSocket := TServerSocket.Create;
FServerSocket.OnClientRead := OnClientRead;
end;
destructor TServerManage.Destroy;
begin
Flock.Free;
ServerActive := False;
FServerSocket.Free; inherited;
end;
function TServerManage.OnClientRead(ASocket: TCustomSocket; AData: Pointer;
ACount: Integer): Integer;
var
Buffer:String;
p:pointer;
dataBlock:TDataBlock;begin
SetLength(Buffer,ACount);
System.Move(Adata^,Buffer[1],ACount);
//处理完成后的返回消息,不论如何处理,都应该向发报机提供一个返回的消息
dataBlock.context := 'testtest';
p := @DataBlock;
ASocket.Write(p^,255); //发送返回的消息 Result := 0;end;
end.client端:
procedure TClient.Execute;
var
p:pointer;
D: TdataBlock;begin
try
StrPCopy(D.Content,Trim(LoginQuery+'|2|2|'+INTTOSTR(CC)));
// d.Content :=LoginQuery+'|2|2|';
inc(cc); FSocket.Open(FHost, FHost, '', DbServerPort);
P := @d;
FSocket.SendBuf(P^,length(d.Content)); //读返回的值
FillChar(D, 255, 0); FSocket.ReceiveBuf(D.Content, 255); FrmMain.Caption := D.Content;
//读完后关闭
finally
Fsocket.Close;
end;
end;现在发现server端的ONClientRead事件执行了两次,请问是什么原因?
unit Servermanage;
//对通信的管理
interface
uses
SysUtils, Classes,Variants, IOCPComp, SyncObjs, comms,Messages;Type TServerManage=Class
private
FLock: TCriticalSection; //锁定标志
FServerSocket: TServerSocket; //服务 FServerActive: Boolean; //服务激活标志 protected
function OnClientRead(ASocket: TCustomSocket; AData: Pointer;
ACount: Integer): Integer;
procedure OnClientError(ASocket: TCustomSocket; ErrorEvent: TErrorEvent;
var ErrCode: Integer);
procedure OnClientEvent(ASocket: TCustomSocket;
SocketEvent: TSocketEvent);
procedure SetServerActive(const Value: Boolean); function GetLoginCount:Integer;//返回登录的总计人数
public
procedure initPort;
procedure StartServer;
procedure StopServer;
procedure RefreshServer;//刷新服务 constructor Create(AOwner: TComponent);
destructor Destroy; override; published
property ServerActive:Boolean read FServerActive write SetServerActive; Property LoginCount:integer read GetLoginCount; End;
implementation
constructor TServerManage.Create(AOwner: TComponent);
begin
inherited Create; FLock := TCriticalSection.Create; FServerSocket := TServerSocket.Create;
FServerSocket.OnClientRead := OnClientRead;
end;
destructor TServerManage.Destroy;
begin
Flock.Free;
ServerActive := False;
FServerSocket.Free; inherited;
end;
function TServerManage.OnClientRead(ASocket: TCustomSocket; AData: Pointer;
ACount: Integer): Integer;
var
Buffer:String;
p:pointer;
dataBlock:TDataBlock;begin
SetLength(Buffer,ACount);
System.Move(Adata^,Buffer[1],ACount);
//处理完成后的返回消息,不论如何处理,都应该向发报机提供一个返回的消息
dataBlock.context := 'testtest';
p := @DataBlock;
ASocket.Write(p^,255); //发送返回的消息 Result := 0;end;
end.client端:
procedure TClient.Execute;
var
p:pointer;
D: TdataBlock;begin
try
StrPCopy(D.Content,Trim(LoginQuery+'|2|2|'+INTTOSTR(CC)));
// d.Content :=LoginQuery+'|2|2|';
inc(cc); FSocket.Open(FHost, FHost, '', DbServerPort);
P := @d;
FSocket.SendBuf(P^,length(d.Content)); //读返回的值
FillChar(D, 255, 0); FSocket.ReceiveBuf(D.Content, 255); FrmMain.Caption := D.Content;
//读完后关闭
finally
Fsocket.Close;
end;
end;现在发现server端的ONClientRead事件执行了两次,请问是什么原因?
第二次实际上AData为空了,但它就是要一直触发onclientread.如果把Asocket.write屏掉,就不会一直触发.
var
p:pointer;
D: TdataBlock;begin
try
D.Content := LoginQuery+'|2|2'; FSocket.Open(FHost, FHost, '', DbServerPort);
P := @d;
if FSocket.Connected then
begin FSocket.SendBuf(P^,length(d.Content)); //读返回的值
FillChar(D, 255, 0); FSocket.ReceiveBuf(D.Content, 255); FrmMain.Caption := D.Content;
//读完后关闭
end;
finally
Fsocket.Close;
end;
end;