这篇文章以前写的,贴到CSDN,现在我也找不到在哪了,从光碟上找的,
呵呵,有什么不明白的再问,:)
************************************************************
一直用socketconnection和服务端的传输数据在三层数据库中,从来没有注意到它们之间
的数据传输,只是想着,管它了,网络的事,前段时间在delphi中的demos中发现
demos/midas/intrcpt.dpr例子,呵呵,再看了半天的vcl发现可以将client端发送的
给server的数据,和server发送给client的数据是可以进行压缩的。呵呵,不敢藏私,
share给大家。
1:
准备工作,先delphi光盘中的/info/extras/zlib/zlib.pas进行编绎,然后copy 到lib路径中,因为要压缩数据,必须要有压缩功能,这个delphi已经自带,它是基于流的方式对接口idatablock(tdatablock实现,其实就是对tmemorystream的操作)数据进行压缩和解压的。做了这个后,才能进行下面的工作。
2:
open /demos/midas/intrcpt/intrcpt.dpr
complier....(如没有做第一步,嘿嘿...)
生成intrcpt.dll
将intrcpt.dll copy to system directory,或者你的程序下面。
注册它:regsrvr32 intrcpt.dll (为什么,这个嘛...)
记住intrcpt.dpr的那个guid,你也可以自己重新生成一个(按shift+ctrl+g)
3:
server:
open scktsrvr.exe,相信各位都很熟悉那界面,端口(tlistbox),thread cache size(tedit), guid(tedit),好,我们要做的事,就是将注册的intrcpt.dll那个guid填到这个guid(tedit)框框中,
只需填自己程序的的那个端口的guid啊,别乱填,如果有别人用这个程序,出了什么,别找我。ok,apply.
client:
你写的程序中肯定有tsocketconnection,它有个属性interceptguid: string;好了,将intrcpt.dll的guid填上去,它是跟server中的一样的。ok.还有别忘了,regsrvr32 intrcpt.dll 在你的客户端。不然,程序虽不会raise,但是server传过来的数据是压缩的....
好了,呵呵。就这些了。3步骤,很清楚吧(不会吧,还不懂,倒)
原理
scktsrvr.exe其实是一堆tserversocket,一个端口代表了一个tserversocket,每个tserversocket是基于多线程方式与客户端进行数据交换。它写了个tserverclientthread(在服务端中的客户端)的扩展
,多加了对客户端数据接收的管理解析,还有activitydatetime,guid,一般不管它。但是我们用到的压缩只是跟这个guid有关,其它费话少说。
server接受一个client连接,则加一个tserverclientthread到本地中,用来监控client read 和close事件,所以server中的scktsrvr中我们只要了解了tserverclientthread动作方式就行了。
(
题外话:server socket中有客户端连接后,记录clientsocket.handle,并且将根据这个handle产生一个tserverclientwinsocket对象加入到connections(tlist)对象中,当任何对这个client的动作也就是说server 发送和接收数据都是根据这个client handle来进行的,相应的serversocket中的connections中的clientsocket也发生相应的变化。
)
有两个类跟这个tserverclientthread(实现isenddatablock接口)有关
1: tdatablockinterpreter(对发送过来的数据进行解析interpretdata(data: idatablock))
解析数据(水平有限,对它真是还是一知半解,有错请指出)
接口类idatablock,由tdatablock通过tmemorystream的读写来实现,其中signature是其主要标识,说明这个idatablock的数据类型 ,tdatablockinterpreter根据signature来对应进行相应的调用, 如:
client端连接后,在server要运行应用服务器(application server),
client端需要得到servername 列表,
client端得到server 的databroker的列表,
client端断开连接后,server要close应用服务器(application server),
client和server的数据交换,也是由它来解析。
所以这个idatablock的数据很重要,而我们的压缩和解压就是针对于它,但是tdatablockinterpreter是得到data才对它解析,因而我们要在send 和recv 之前对它解压和压缩。这个任务在tsockettransport身上。
2: tsockettransport;(数据进行发送和接收, 实现itransport接口)
server端:
在server端,tsockettransport其实就是一个用来管理对clientsocket实例,它将clientsocket.handle生成一个对象后,clientsocket发送和接收过来的data,在发送data之前,它将调用interceptoutgoing(data: idatablock)函数,这个函数的功能是:
如果interceptguid <> '',那么它将根据这个guid生成一个com(obj)对象,obj.dataout(data: idatablock),也就是我们注册的那个压缩的dll中的那个压缩函数,将压缩过后的data再发送出去。这就完成compress and send data.(我试过那个压缩功能,压缩比大概是1/9,像zip压缩比差不多).
由客户端传过来的数据调用interceptincoming(data: idatablock)函数,这就不多说了,data := 解压后的data. 压缩和解压过后的data交由tdatablockinterpreter去解析,完成一次数据交换。
client端:
说完server端,客户端的道理也是差不多的。唯一不同的是server端中不调用itransport.setconnected()方法,因为它是根据clientsocket.handle生成的对象,也就是它是已经连接的对象,而client端的tsocktconnection调用connected := true时,其实就是调用itransport.setconnect将一个clientsocket连接到server端中的tserversocket中,然后tserversocket根据这个clientsocket.handle生成了一个tserverclientthread对象保存在本地中,开始对这个clientsocket的监控(fd_read, fd_close消息事件).
注:
idatablock由tdatablock实现,主要是管理tmemorystream来存放数据
itransport由tsockettransport实现,主要是用tclientsocket来连接tserversocket,并和它进行交换数据。
isenddatablock在scktsrvr.exe中由tserverclientthread实现,通过tsockettransport来发送数据.
说了这么多,想必各位很明白了吧。:)