手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>delphi>列表

读一读Scktsrvr.exe的源程序

来源:互联网 作者:西部数码 时间:2008-04-09
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!


读一读Scktsrvr.exe的源程序

使用DELPHI做多层开发的朋友们都应该对Scktsrvr.exe这个程序不陌生的,
Borland公司在DELPHI中给出了它的源代码。
这是一个900来行的程序,程序不算长,
现在我只选其中部分仔细读一读。
走的线路大致是,从服务器接到客户端连接,处理客户端的一个请求(这儿
选了客户端向服务器发出的''''取应用服务器列表''''请求)


服务器接受了客户端连接后,
因为ServerSocket采用的是阻塞模式,服务器执行了下面这个线程来
服务客户端:


//SCKTMAIN.PAS

procedure TSocketDispatcherThread.ClientExecute;
var
Data: IDataBlock;
msg: TMsg;
Obj: ISendDataBlock;
Event: THandle;
WaitTime: DWord;
begin
CoInitialize(nil); //初始化COM
try
Synchronize(AddClient); //在程序界面上显示客户信息,
//用同步保证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;
while not Terminated and FTransport.Connected do
try
case MsgWaitForMultipleObjects(1, Event, False, WaitTime, QS_ALLEVENTS) of
//MsgWaitForMultipleObjects保持线程同步之用,
//本文暂不细说它.
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;
就这么舒舒服服的六十来行。
除开那些流程控制的语句,我们主要看到两个东西:
数据传输(FTransport) 和 数据解析(FInterpreter)。

在本文中,我更感兴趣的是它的应用协议的实现,
数据传输(FTransport)就先扔在一边,以后再看了.

现在我们就来看看它的数据解析部分。
。。。
FInterpreter := TDataBlockInterpreter.Create(Obj, SSockets) else
FInterpreter := TDataBlockInterpreter.Create(Obj, '''''''');
//这两种创建TDataBlockInterpreter类实例的方法的区别也不去管它.
。。。
FInterpreter.InterpretData(Data);
。。。
就是这儿,就是这么一句。
它具体到底干了些什么呢??
================
。。。
type
TSocketDispatcherThread = class(TServerClientThread, ISendDataBlock)
private
。。。
FInterpreter: TDataBlockInterpreter;
FTransport: ITransport;
。。。

================
FInterpreter这个对象引用就是这儿定义的。


procedure TDataBlockInterpreter.InterpretData(const Data: IDataBlock);
var
Action: Integer;
begin
Action := Data.Signature;//取出由客户端传来的数据块中请求标志值
//客户端数据块的具体数据格式等会儿说.
if (Action and asMask) = asError then DoException(Data);
try
case (Action and asMask) of //根据客户端的请求标志值作相应的处理.
//呵,就只有这么几个。一个大型的MIDAS系统
//就全站在它们肩上.
asInvoke: DoInvoke(Data);
asGetID: DoGetIDsOfNames(Data);
asCreateObject: DoCreateObject(Data);
asFreeObject: DoFreeObject(Data);
asGetServers: DoGetServerList(Data);
asGetAppServers: DoGetAppServerList(Data);//取这个再进一步读一读.
else
if not DoCustomAction(Action and asMask, Data) then
raise EInterpreterError.CreateResFmt(@SInvalidAction, [Action and asMask]);
end;
except
on E: Exception do
begin
Data.Clear;
WriteVariant(E.Message, Data);
Data.Signature := ResultSig or asError;
FSendDataBlock.Send(Data, False);
end;
end;
end;
==========================
顺着线一步步摸下去,
看它是怎么取APPSERVER列表返回客户端的。

很简单,就是通过GetMIDASAppServerList取本地的MIDAS应用服务

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!