分享
 
 
 

读一读Scktsrvr.exe的源程序

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

读一读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应用服务

器列表,然后将其写在Data中,传回客户端就了事。

===========================

procedure TDataBlockInterpreter.DoGetAppServerList(const Data: IDataBlock);

var

VList: OleVariant;

List: TStringList;

i: Integer;

begin

Data.Clear;

List := TStringList.Create;

try

GetMIDASAppServerList(List, FCheckRegValue);//取本机的应用服务器列表

//想知道它是怎么做的吗?

//源码上都有,自己看.

if List.Count > 0 then

begin

VList := VarArrayCreate([0, List.Count - 1], varOleStr);

for i := 0 to List.Count - 1 do

VList[i] := List[i];

end else

VList := NULL;

finally

List.Free;

end;

WriteVariant(VList, Data);

Data.Signature := ResultSig or asGetAppServers;

FSendDataBlock.Send(Data, False);//将应用服务器列表传回客户端

end;

========================================================

哦..前面还有一个地方没有说,就是这个神秘的Data的数据格式,它是以接口

形式提供的,

这个程序中用的是TDataBlock中实现的这个接口.

源码中可以看出,TDataBlock中包含了一个Stream,

function TDataBlock.GetSize: Integer;

begin

Result := FStream.Size - BytesReserved;//BytesReserved的值这儿是8

end;

从这儿可以看出.数据块是从Stream的第8个字节算起,前面就是两个int型数的位置了.

function TDataBlock.GetSignature: Integer;

begin

FStream.Position := 0;

FStream.Read(Result, SizeOf(Result));

end;

呵, 没错, Stream的头四字节就是它的Signature.客户端的请求标志就是放在这儿.

function TDataBlock.GetStream: TStream;

var

DataSize: Integer;

begin

FStream.Position := 4;

DataSize := FStream.Size - BytesReserved;

FStream.Write(DataSize, SizeOf(DataSize));

FStream.Position := 0;

Result := FStream;

end;

这儿很明显,就是Data中包含数据的长度值.

需要提一下的是,如果你想改变一下传输数据块的格式,比如给它加密加压什么的,

中需要自己来实现IDataBlock接口,替掉TDataBlock就是了.

从这些源码中可以得到很多东西,无论是从优美的风格上,

无论是通讯程序开发还是MIDAS数据库以及DCOM学习或应用者,

它都是值得一读的源程序.

我觉得,更重要的是,它提供了一个严谨优美和实际的范例,更给出了

一个灵活实用的框架体系。

halfdream(哈欠) 于2001-10-14晚

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有