{這是我根據Borland Socket Service改寫的類:TListenSocket, 它的功能是相當於:"X:Program FilesBorlandDelphi5Binscktsrvr.exe"。也是說它可以將你的分布式服務端程序變成一個有偵聽功能的程序,有偵聽,還有你的Remote DataModule可以照樣運行。寫出來不久,如果有什麼BUG,請指出,謝謝。}
{本想把它做成控件方式的,現在不想去改動了。有需要再說,}
{
用法:
uses Listensocket;
var Socket:TListenSocket;
const ListenPort=8888;
Socket:=TListenSocket.Create(Self);
Socket.ListenPort:=ListPort;
Socket.Open;
//OK
}
unit ListenSocket;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SConnect,ScktComp,SvcMgr, ActiveX,MidConst,winsock,MyConst;
var
FClientThreads:TList;
type
TSocketDispatcherThread = class(TServerClientThread, ISendDataBlock)
private
FRefCount: Integer;
FInterpreter: TDataBlockInterpreter;
FTransport: ITransport;
FLastActivity: TDateTime;
FTimeout: TDateTime;
FRegisteredOnly: Boolean;
procedure AddClient;
procedure RemoveClient;
protected
function CreateServerTransport: ITransport; virtual;
{ procedure AddClient;
procedure RemoveClient; }
{ IUnknown }
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
{ ISendDataBlock }
function Send(const Data: IDataBlock; WaitForResult: Boolean): IDataBlock; stdcall;
public
constructor Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket;
const InterceptGUID: string; Timeout: Integer; RegisteredOnly: Boolean);
procedure ClientExecute; override;
end;
type MyServerSocket=Class(TServerSocket)
private
procedure GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;var SocketThread: TServerClientThread);
public
constructor Create(AOwner: TComponent); override;
end;
type
TListenSocket = class(TObject)
private
FActive:Boolean;
FListPort :integer;
FCacheSize :integer;
SH:MyServerSocket;
FItemIndex :integer;
procedure SetActiveState(Value:boolean);
function GetClientCount :integer;
{ Private declarations }
public
property CacheSize :integer read FCacheSize write FCacheSize;
property ListPort:integer read FListPort write FListPort;
property Active :boolean read FActive write SetActiveState;
property ClientCount:integer read GetClientCount;
public
constructor Create(AOwner :TComponent);
destructor Destroy;override;
class procedure AddClientThread(Thread :TSocketDispatcherThread);
class procedure RemoveClientThread(Thread:TSocketDispatcherThread);
procedure Open;
procedure Close;
end;
implementation
function TListenSocket.GetClientCount :integer;
begin
Result:=FClientThreads.Count;
end;
constructor TListenSocket.Create(AOwner :TComponent);
begin
LoadWinSock2;
FActive:=False;
FClientCount:=0;
FCacheSize :=10;
FClientThreads:=TList.Create;
SH:=MyServerSocket.Create(nil);
inherited Create;
end;
destructor TListenSocket.Destroy;
begin
SetActiveState(False);
FreeAndNil(FClientThreahs);
inherited Destroy;
end;
procedure TListenSocket.Open;
begin
SetActiveState(True);
end;
procedure TListenSocket.Close;
begin
SetActiveState(False);
end;
class procedure TListenSocket.AddClientThread(Thread :TSocketDispatcherThread);
begin
FClientThreads.Add(Thread);
end;
class procedure TListenSocket.RemoveClientThread(Thread :TSocketDispatcherThread);
var i:integer;
begin
for i:=0 to FClientThreads.Count -1 do
begin
i:=FClientThreahs.IndexOf(Thread);
if i<>-1then
FClientThreads.Delete(i);
end;
end;
procedure TListenSocket.SetActiveState(Value:boolean);
var i:integer;
begin
if Value then
begin
SH.Close;
SH.Port :=ListPort;
SH.ThreadCacheSize :=CacheSize;
SH.Open;
end else
if not Value then//if FClientCount>0 then Error(還有客戶在連接狀態,中止。)
SH.Close;
FActive:=Value;
end;
//下面的東西都是在Delphi中Copy過來的,為我所用了。呵呵
{MyServerSocket Class}
procedure MyServerSocket.GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread:=TSocketDispatcherThread.Create(false,ClientSocket,,0,false);
end;
constructor MyServerSocket.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ServerType := stThreadBlocking;
OnGetThread := GetThread;
end;
{MyServerSocket Class over}
{TSocketDispatcherThread class}
function TSocketDispatcherThread.CreateServerTransport: ITransport;
var
SocketTransport: TSocketTransport;
begin
SocketTransport := TSocketTransport.Create;
SocketTransport.Socket := ClientSocket;
Result := SocketTransport as ITransport;
end;
constructor TSocketDispatcherThread.Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket;
const InterceptGUID: string; Timeout: Integer; RegisteredOnly: Boolean);
begin
FTimeout:=EncodeTime(Timeout div 60, Timeout mod 60, 0, 0);
FRegisteredOnly:=RegisteredOnly;
FLastActivity:=Now;
inherited Create(CreateSuspended, ASocket);
end;
function TSocketDispatcherThread.Send(const Data:IDataBlock; WaitForResult:Boolean):IDataBlock;
begin
FTransport.Send(Data);
if WaitForResult then
while True do
begin
Result := FTransport.Receive(True, 0);
if Result = nil then break;
if (Result.Signature and ResultSig) = Resul