****新年贺礼----TListenSocket*****

saoren 2001-01-29 08:34:00

新年好,新年进步,给大家献上新年礼物,我写的一个类似:Borland Socket Service功能的类,并请大家指出错误。
本想藏私,不过,没有交流,就没有进步,所以大家进步,哈哈,
用法简单:
uses ListenSocket;
SH:TListenSocket;

SH:=TListenSocket.Create(Self);
SH.ListPort:=8888;
SH.Open;
//OK.你的(SERVER)程序变成一个侦听程序了。oh



unit ListenSocket;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SConnect,ScktComp,SvcMgr, ActiveX,MidConst,winsock,MyConst;

var FClientCount:integer;
FClientThreads:TStringList;
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:=FClientCount;
end;

constructor TListenSocket.Create(AOwner :TComponent);
begin
LoadWinSock2;
FActive:=False;
FClientCount:=0;
FCacheSize :=10;
FClientThreads:=TStringList.Create;
SH:=MyServerSocket.Create(nil);
inherited Create;
end;

destructor TListenSocket.Destroy;
begin
SetActiveState(False);
FClientThreads.Free;
inherited Destroy;
end;

procedure TListenSocket.Open;
begin
SetActiveState(True);
end;

procedure TListenSocket.Close;
begin
SetActiveState(False);
end;

class procedure TListenSocket.AddClientThread(Thread :TSocketDispatcherThread);
begin
Inc(FClientCount);
FClientThreads.AddObject(Thread.ClientSocket.RemoteHost,Thread);
end;

class procedure TListenSocket.RemoveClientThread(Thread :TSocketDispatcherThread);
var i:integer;
begin
for i:=0 to FClientThreads.Count -1 do
begin
if TSocketDispatcherThread(FClientThreads.Objects[i])=Thread then
begin
FClientThreads.Delete(i);
Dec(FClientCount);
end;
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
SH.Close;
FActive:=Value;
end;

{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) = ResultSig then
break else
FInterpreter.InterpretData(Result);
end;
end;

procedure TSocketDispatcherThread.AddClient;
begin
TListenSocket.AddClientThread(Self);
end;

procedure TSocketDispatcherThread.RemoveClient;
begin
TListenSocket.RemoveClientThread(Self);
end;

procedure TSocketDispatcherThread.ClientExecute;
var
Data: IDataBlock;
msg: TMsg;
Obj: ISendDataBlock;
Event: THandle;
WaitTime: DWord;
begin
CoInitialize(nil);
try
Synchronize(AddClient);
FTransport := CreateServerTransport;
try
Event := FTransport.GetWaitEvent;
PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
GetInterface(ISendDataBlock, Obj);
if FRegisteredOnly then
FInterpreter := TDataBlockInterpreter.Create(Obj, SSockets) else
FInterpreter := TDataBlockInterpreter.Create(Obj, '');
try
Obj := nil;
if FTimeout = 0 then
WaitTime := INFINITE else
WaitTime := 60000; //MAXIMUM_WAIT_OBJECTS
while not Terminated and FTransport.Connected do
try
case MsgWaitForMultipleObjects(1, Event, False, WaitTime, QS_ALLEVENTS) of
WAIT_OBJECT_0:
begin
WSAResetEvent(Event);
Data := FTransport.Receive(False, 0);
if Assigned(Data) then
begin
FLastActivity := Now;
FInterpreter.InterpretData(Data);
Data := nil;
FLastActivity := Now;
end;
end;
WAIT_OBJECT_0 + 1:
while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
DispatchMessage(msg);
WAIT_TIMEOUT:
if (FTimeout > 0) and ((Now - FLastActivity) > FTimeout) then
FTransport.Connected := False;
end;
except
FTransport.Connected := False;
end;
finally
FInterpreter.Free;
FInterpreter := nil;
end;
finally
FTransport := nil;
end;
finally
CoUninitialize;
Synchronize(RemoveClient);
end;
end;

function TSocketDispatcherThread.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
end;

function TSocketDispatcherThread._AddRef: Integer;
begin
Inc(FRefCount);
Result := FRefCount;
end;

function TSocketDispatcherThread._Release: Integer;
begin
Dec(FRefCount);
Result := FRefCount;
end;
{TSocketDispatcherThread class over}

end.
...全文
307 5 打赏 收藏 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Kingron 2001-06-04
  • 打赏
  • 举报
回复
鼓掌!
saoren 2001-06-01
  • 打赏
  • 举报
回复
给分
halfone 2001-01-30
  • 打赏
  • 举报
回复
我的看看!
YunEr 2001-01-30
  • 打赏
  • 举报
回复
很好呀!我在看!
saoren 2001-01-30
  • 打赏
  • 举报
回复
无人问津?
下载代码方式:https://pan.quark.cn/s/c66ecb4d06ce 同源策略:从安全角度出发,浏览器会对脚本发起的跨站请求施加限制,要求JavaScript或Cookie仅能获取同源(即协议、域名和端口完全一致)下的资源。正因如此,不同项目间的调用会受到浏览器的阻碍。以常见情境为例:WebApi作为数据服务层,它是一个独立的项目,而MVC项目则承担Web的展示功能,此时MVC项目需要调用WebApi中的接口以获取数据并在页面上呈现。由于WebApi与MVC属于两个独立的项目,运行后便会产生前面提及的跨域问题。WebApi的跨域问题主要源于浏览器的同源策略,这是一种安全措施,旨在限制JavaScript或Cookie仅能访问同一源(包括协议、域名和端口)下的内容。在实际开发过程中,当WebApi作为一个独立服务,例如数据服务层,而MVC项目作为前端展示层时,两者运行在不同的项目和端口下,浏览器将阻止MVC对WebApi的跨域请求,从而影响数据的正常获取。为了应对这一问题,我们可以采用CORS(跨域资源共享)机制。CORS通过在HTTP请求与响应头中嵌入特定标识,向浏览器明确哪些跨域请求是被允许的。例如,服务器可以在响应头中添加`Access-Control-Allow-Origin:http://localhost:8081`,表示允许来自http://localhost:8081的请求访问资源。解决WebApi跨域问题的具体实施步骤如下: 1. 构建一个包含MVC项目(Web)与Web API项目(WebApiCORS)的解决方案。 2. 在MVC项目中,例如Home控制器的Index视图,通过Ajax向WebApiCORS发起跨域请求。 3...

5,943

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧