P2PSDK开发包与无关性协议传输.doc_第1页
P2PSDK开发包与无关性协议传输.doc_第2页
P2PSDK开发包与无关性协议传输.doc_第3页
P2PSDK开发包与无关性协议传输.doc_第4页
P2PSDK开发包与无关性协议传输.doc_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

P2P SDK开发包与无关性协议传输目录:一综述二PPQ.DLL是一个P2P SDK开发包三PPQ.DLL的特点四PPQ.DLL的工作方式五创建PBaseAct派生类六在开始一个任务之前的准备工作七从URL下载一个文件八建立一个语音聊天九从另一个好友处下载一个文件十PPQ.DLL的无关性协义传输一综述 PPQ.DLL通过对象和插件的封装来实现无关性协义传输,允许开发者在不必知道传输协议的前提下,就可以进行插件的开发,加快开发过程,减少错误的产生,提供了一种用TCP来实现事务处理的策略,在最后提出了一种比HTTP、XML和SOAP等更加灵活的包含执行方法的,以传送对象的方式实现的无关性协义传输。 二PPQ.DLL是一个P2P SDK开发包PPQ.DLL是一个P2P的SDK开发包,它使用对象的传递来实现无关性协议传输,这种对象并不是MFC或JAVA的序列化对象,PPQ.DLL的序列化对象,使开发者可以在互相不知道传送协议的情况下,互传消息,并且可以根据开发者的定义,在不同的编程语言环境中互传对象。它将TCP的流式数据转变成一个个事务来对待,每一个事务表明你希望通过P2P来实现的功能,事务的处理过程可以使用DLL、OCX或COM等任何一种形式封装起来,这些被封装的事务可以由其它开发者直接在自己的开发程序中引用,而不需要再为处理相同的事务去开发一套程序。 PPQ.DLL采用插件的形式来引用已定义好的事务处理程序,不但可以在开发程序时增加一个插件,而且允许程序在运行时动态增加或取消一个插件,使开发出来的程序,具备动态扩展功能,而不必每增加一个功能都重新发布一次程序,并且这种插件地增加和取消可以完全由用户自己来决定。PPQ.DLL封装了数据传输时的编码方式,使开发者不用担心开发程序与未来P2P国际标准之间的接轨,对于新的标准的适应,只需要简单的修改一下底层的解码器,所有原先的开发程序就可以自动地适应新的国际标准。PPQ.DLL实际上提供了一种新的以对象方式实现的无关性协议传输,它类似于XML、HTTP、SOAP等协义,但有其独特的特点,关于这种新的无关性协议传输的可行性将在后面论述。 PPQ.DLL为P2P的应用带来了一个新的起点。现在的P2P的应用都是传递一种字符串来作为命令,它只能传递规则,而无法传递规则所表示的方法,并且这种规则到目前为止并没有一个统一的标准,如何建立标准与什么时候能够建立标准都是一个期待的问题。在等待标准公布时,每一家大的公司都在努力制定自己的协义与标准,都希望将来的标准能够与自己的相同,在标准公布以后,所有的与标准不同的程序,如果想适应标准,都必需去修改原程序,这个改动是很庞大的,而PPQ.DLL正是解决了这个问题。PPQ.DLL的传输没有任何的协议,任何一个开发者都可以制定自己的协议标准去完成一个任务,而不需要去关心其它的应用程序。对于想通过P2P来实现的功能,只需要加入一个已经定义好的类就可以啦,如果想在其它开发者开发的事务处理程序基础之上去增加一些功能,甚至可以从其他开发者已经定义好的类中派生出新的本地类来实现自己的独特功能,而发送指令对象的双方却都可以正确地解析,并且可以在双方的处理过程中,都引入自己独特的本地处理方式。PPQ.DLL是一种真正地无协义传输方式,它的引入可以使P2P在一些关键性领域中得到真正地应用,它的这种插件式自由组合方式,也使程序地开发得到了最大化的复用,能够更好地加快程序开发速度,使每一次的开发都不必再从起跑线上开始。利用PPQ.DLL的对象传递方式,PPQ.DLL将P2P实现的基本功能都封装在了DLL中,开发者可以直接把它作为一个开发包来使用,其他开发者利用PPQ.DLL的对象传递方式开发出的插件,也可以直接无缝地加入开发包中,使开发P2P产品变得轻松自如。PPQ.DLL也提出了防止目前P2P上盗版、黄色信息、无用的垃圾信息大量泛滥的一种方法,让P2P的使用更加规范,使个人用户的行为更加具有针对性和目的性。从开发JAVA版的P2P程序开始,我就始终认为P2P应该对下载的文件设定一种权限,用户通过权限可以控制自己所提供的文件可以被哪一些人下载,这种想法也影响到了我开发C+版的PPQ.DLL。国内目前开发的P2P程序中对下载文件都没有任何的限制,其直接导制的后果就是大量的黄色信息呈辅射状传播,一个下载了黄色信息的用户无形之中成为了一个传播黄色信息的新的源,形成了非常坏的一个恶性循环,最终导制目前国内所有P2P网站全部暂停。PPQ.DLL对用户的所有传送文件采用数字标识来传递,这种数字标识可以和一些描述性的词汇一起被传送给其它用户,用户想下载时,也是传递数字标识,而并不是直接传递想下载的文件名,传送方在接收到数字标识后通过程序去查找到该数字标识所对应的正确的本地文件名,在这个过程中,传送方可以检验请求传送的用户是否有权限下载该文件,如果有,则开始传递文件,否则会驳回该用户的请求。数字标识的引入为安全性和扩展性带来了很多的好处:1用户不必再设定某一个共享目录,文件可以散布在本地机器的任何一个目录下,而不用担心安全性。2避免了垃圾文件的出现,设定共享目录时,用户常常将一大堆文件拷贝到目录下,结果检索出来的经常是一大堆垃圾。3可以为任何一个文件加入权限设定,使用户可以灵活得控制每一个文件的一个或一组下载方。4每一下载方只能看到自己可以下载的内容,不在权限内的下载内容根本就看不到。5为将来的应用增加了可扩展性,从数字标识到正确的本地文件的转换过程,提供了一种方便地扩展手段,以什么方式来设定权限、如何校验权限、是否使用权限、以及对不同文件采取不同加密手段等都可以在这个转换过程中根据具体情况来定义。 通过以上方法,只能防止文件的泛滥传播,还不能有效地控制黄色信息。从用户端来控制黄色信息是很困难的,因为写的任何一个过滤代码都很容易就会被破解,从而根本起不到过滤黄色信息的目的,所以最终还是应该从服务器来控制。PPQ.DLL的想法是将用户提供的公共信息源采用分布式数据库的方式保存,由专门的服务器提供一个强大的搜索引擎,用户通过这个搜索引擎来检索公共信息,在这个搜索引擎中设置过滤器,滤除黄色信息,这是避免黄色信息泛滥传播的一个有效方法。(用户在几个人的小范围内进行的传播,应该不在考虑范围之内,而且也根本就不可能完全地控制住。)PPQ.DLL在服务器开发方面,提出了一种“全球服务器统一资源分配”策略,这种方式,对服务器的负担非常轻,可以由任意多个服务器提供商去独立地创建自己的用户群,建立自己的用户档案库,彼此间不需要频繁交换信息,也不需要彼此共享用户资源,更用不着建立中心数据库,但是在任何一台服务器上登录的用户彼此间却可以互相通讯,可以不通过服务器而建立连接。 三PPQ.DLL的特点1在P2P标准尚未统一的情况下,开发者都在独立的制定自己的传送协议,使开发出来的程序彼此无法互相通讯,而且采用不同编程语言开发出的产品,在互相通信时也会存在问题,PPQ.DLL正是为解决这个问题而开发的。PPQ.DLL是建立在任何一种标准协议之上的一种公共接口,它不但能简化开发过程,而且标准化了传送和接收的过程,使开发者可以在各自制定协议的前提下,仍然能够实现互相通讯,并且可以在采用不同的编程语言开发的产品之间互相传递指令对象。2PPQ.DLL封装了采用TCP进行文件传送与接收的全过程。只需要给出连接方的IP地址、监听端口号和想传送(或下载)的文件的数字标识号,PPQ.DLL会自动地以多线程、断点续传的方式实现文件的传送与接收过程。3PPQ.DLL封装了以HTTP方式从URL地址下载文件的全过程。只需要给出想下载的URL地址,PPQ.DLL会自动地根据服务器端是否支持断点续传,来决定采用单线程还是多线程方式下载。支持重定向。4PPQ.DLL封装了以TCP方式进行语音聊天的全过程,只需简单地调用几个静态函数,就可以轻易地启动、暂停、关闭声音捕捉(录音)和声音回放(放音),并初步实现了静音过滤。5PPQ.DLL封装了进行数据传输的编码方式和传送的具体过程,将数据的传送和接收转变成对象的传送和接收,使处理过程标准化。使用PPQ.DLL来开发程序,不用直接和字符串打交道,不必再去解析从SOCKET接收到的字符串编码,开发者可以将想传送的信息定义成指令对象的属性,直接发送指令对象,PPQ.DLL会自动将指令对象转变成数据流发出。SOCKET所接收到的数据,PPQ.DLL会自动转变成对应的指令对象,以WINDOWS消息或回调函数的方式通知接收方,使整个的开发过程变得更加简单和模块化。6PPQ.DLL的对象数据流处理并不是MFC的序列化对象,它比MFC的序列化对象更加简单、易用,允许在修改对象属性后,重复发送对象,而且能够在无法实别所传送的类对象时,自动还原成与该类最接近的一个基类的对象。PPQ.DLL的序列化解码过程采用纯C+编写,可以很容易地改写成其它的语言。7PPQ.DLL的对象流的实现过程和方法被完全地封装在了DLL中,对于实现对象流的算法的优化,甚至是改变对象流的传送格式,都不会对使用PPQ.DLL的开发者造成任何影响,使开发者可以完全放心地开发程序,而不用担心标准与协议的改变。经过数次的改写和优化,正式版的PPQ.DLL不但可以传送任意大小的指令对象,并且在接收指令对象时,从SOCKET中读出的数据将直接被写到指令对象相应的属性的缓冲区中,中间不再需要经过任何一次缓冲区的复制过程,大大地加快了速度。8如果你认为使用PPQ.DLL开发的不同产品,只不过是界面上的不同,那你就错啦。PPQ.DLL提供了丰富的接口和灵活的开发方式,使你完全可以开发出具有鲜明特点和独立功能的程序。PPQ.DLL只是封装了连接实现的过程和握手协议,对建立连接后,双方传送的信息并没有作出任何规定和假设,它只是提供了一种公共的接口。9开发者可以根据自己的需要去创建新的类,来表明一种类型的指令,这种类型的指令完成一种特定的功能,开发者可以将自己创建的指令和指令的解析程序一起打包成一个DLL,发布出来,同时公布该类的ClassID。其它的开发者可以在自己的程序中直接引用这个DLL,来完成由其它开发者预先定义好的功能。PPQ.DLL内部也定义了一些派生类,这些派生类都是完成一种特定功能的指令对象。10PPQ.DLL提供了一个钩子函数,用来返回开发者自定义的类的对象。如果你的自定义类是你发布的DLL中的一个内部类,即自定义的类被完全地封装在了你提供的DLL中,那么这个类的类名可以是任意的,不用担心会重名。当其他开发者要使用你的DLL时,只需要增加你提供的钩子函数即可。但是类的ClassID还是需要公布的,以避免与其他开发者的ClassID重复。握手协议的传递和语音聊天的传送与接收采用的就是指令对象的方式来进行传送,这些对象都被封装在了PPQ.DLL内部,开发者只需要通过接口来启动一个或一组功能,而不需要直接去同这些对象打交道。因为这些类被完全地封装在了PPQ.DLL内部,因此,即使你在开发过程中定义了一个与这些对象重名的类,也不会对程序造成任何的影响。 四 PPQ.DLL的工作方式PPQ.DLL通过消息与回调函数和DLL外部进行交互,要想正确地使用这个DLL,就需要了解PPQ.DLL中对外发布的几个类。PPQ.DLL中一共对外提供了5个类:PDefine、PFriend、PBaseAct、PTask和CStringEx。 PDefine类中定义了开发者需要使用的结构、回调函数、常量以及PPQ.DLL定义的一些消息和静态方法。这个类不需要去创建实例,它里面的所有方法和属性都是静态的。这些定义对正确地了解和撑握PPQ.DLL是非常关键的。 PPQ的整个连接过程是建立在一种信任的基础之上的。即如果A信任B,B也信任A,那么A与B之间可以互相连接,否则连接不能被建立。这种信任的关系不能够被继承,即如果A信任B,B信任A、C,C信任B,这并不表示A也信任C,A可以和B之间互连,B即可以和A,也可以和C之间互连,但A不可以和C这间互连。即信任只能是双方的事情。这种信任关系的表现的实体,就是PFriend类。PFriend类中定义了被连接方的身份标识(ID)、IP地址、监听端口号等相关信息,是对被连接方的一个描述(连接与被连接都是从自己这一方来看的)。通常开发者需要从该类中派生出新的类,以记录关于被连接方的更多的详细资料。在PPQ.DLL中,被连接的一方都称为好友,每一个好友都必需有一个PFriend对象与之对应,除了进行HTTP连接时不需要用到PFriend对象,其它进行的所有连接都是针对于某一个PFriend对象而进行的。希望互相连接的双方,彼此都必需包括有对方的PFriend对象,否则连接是无法被建立的。 PPQ.DLL认为要传输的数据应该被分为2种,一种是指令,表示完成某一种功能,另一种是数据,它的实际意义由以前传递的指令来表明。指令和数据往往是相关连的,失去任何一方,都会失去其表示的有效意义,因此,这2种实际应该是一个整体,而这个整体在PPQ.DLL中表现出的实体,就是PBaseAct类。指令和数据被封装在一个PBaseAct类中,作为一个整体来传输,这就是指令对象。PBaseAct是所有可以转变为数据流进行传输的指令对象的基类,开发者需要自定义传输对象时,都需要从该类来派生出新的类。只有该派生类的实例才可以直接作为一个对象从SOCKET中进行传送与接收。 建立连接应该是有目的性的,即建立连接应该是为了具体完成某一项工作,建立多个连接的目的是为了更好、更快地协同完成这项工作。在PPQ.DLL里,某一项工作用任务来表示,而任务的表现实体,就是PTask类。PTask类描述并记录了一个或一组具有相同连接类型的连接,它表明了要进行的一个任务。 CStringEx类是针对于MFC的CString类的一个扩展,它的主要作用是传递大数据量的二进制流缓冲,通过操作符重载,CStringEx类可以使用+=符号,直接追加一个字符串或一个int类型的数字。通过方法,还可以追加一个中间包含0终结符的二进制的流缓冲。你可以使用CStringEx类在任何一个需要动态改变缓冲区大小的地方,代替原来的数据缓冲区,包括字符缓冲区、音频缓冲区、视频缓冲区等接收缓冲区,使用CStringEx就和使用一个char*是一样的,在使用过程中,你可以直接得到CStringEx的数据缓冲区,将它转换成任意类型的缓冲区来使用。CStringEx对象用来保存指令对象中需要传送的大型数据,在构成指令对象时,如果指令对象需要发送比较长的数据(建议超过1K)时,都应使用CStringEx来保存,因为在传送指令对象时,对CStringEx对象作了优化处理,它的传送速度会比传送CString类型的对象要快得多。 五 创建PBaseAct派生类PPQ.DLL没有对外提供任何的指令对象,因此,使用DLL的第一件事情,就是创建自己的PBaseAct派生类。创建PBaseAct派生类其实很简单,按照以下步骤,你就可以轻松地创建出自己的派生类。1在派生类的.h文件中加入SELF_SERIALIZE()序列化宏。SELF_SERIALIZE()宏需要传递2个参数,第一个参数是当前派生类的类名,第二个参数是该派生类的直接基类的类名。即如果你的派生类名为PLoginAct,它由PChatAct类派生,则宏调用为SELF_SERIALIZE(PLoginAct,PChatAct);2在派生类中重载CountSerializeLength()方法。3在派生类中重载UniteValue()方法。4在派生类中重载InitObject()方法。5在派生类中重载GetClassID()方法,返回自定义类的ClassID。6实现GOCALLBACK钩子函数,返回自定义对象的一个实例。 关于GOCALLBACK钩子函数的定义和实现方法,请查阅PDefine.h文件中的回调函数说明。7实现GETCALLBACK回调函数,对自定义对象进行处理。 或者定义一个PMSGINFO结构,通过消息来处理自定义对象。 关于GETCALLBACK回调函数和PMSGINFO结构的定义和实现方法,请查阅PDefine.h文件中的回调函数说明和结构说明。8如果在第7步中定义了一个PMSGINFO结构,则在派生类中重载基类PBaseAct中的virtual LPPMSGINFOGetCallBackMsg()方法,返回指向PMSGINFO结构的指针。如果在第7步中实现了GETCALLBACK回调函数,则在派生类中重载基类PBaseact中的virtual GETCALLBACK* GetParseActFunPointer()方法,返回指向GETCALLBACK回调函 数的指针。这两个函数你只需要重载一个,建议重载GETCallBackMsg()方法,通过消息来处理指令对象。如果两个函数都重载了,将优先处理回调函数。9调用PDefine:SetUserGetObjectFunHook(),将在第6步中实现的GOCALLBACK钩子函数的地址作为参数传递。六 在开始一个任务之前的准备工作PPQ.DLL会向DLL的外部传递一些很重要的消息,这些消息必需被响应,否则PPQ.DLL无法正常正作。另外,还有一些是必需赋值的静态属性,被定义在了PDefine类中。1 初始化PDefine:rSMsgInfo结构。2 实现回调函数GETPALCALLBACK,并将回调函数的地址赋给PDefine:pSGetFriendCallBackFun属性。3 实现回调函数GETFILENCALLBACK,并将调函数的地址赋给PDefine:pSGetFileNCallBackFun属性。4 为PDefine:szSelfFriendID属性赋初值,表明自己的ID。5 为以下消息创建响应函数:OMSG_CREATE_NEW_OBJ,OMSG_CREATE_NEW_TASK,OMSG_ALL_CONNECT_END,OMSG_MISSION_END6 调用PDefine:SInitSocketStream()方法初始化Win Socket,使创建SOCKET连接成为可能。7 调用PDefine:SCreateTCPListenPort()方法创建TCP监听端口。8 调用PDefine:SSetUserGetObjectFunHook()方法设定钩子函数。9 为想建立连接的对方,建立PFriend对象,并填写上他ID、IP地址和TCP监听端口号。 七 从URL下载一个文件最简单的任务就是从URL下载一个文件。PPQ.DLL封装了通过HTTP下载的全过程,你想在自己的软件中增加网络蚂蚁和FlashGet的功能吗?不要着急,使用PPQ.DLL,你只需要调用几个函数,就可以实现自动下载的过程。1 在堆中创建一个PRECVINFO结构。LPPRECVINFO lprInfo=new PRECVINFO();2 初始化结构,这步是必需的,每创建一个PRECVINFO结构,就应该调用以下的方法初始化结构。memset(lprInfo,0,DWORD(&lprInfo-nPort)-(DWORD)lprInfo);3 设定URL地址。lprInfo-strSrvURL =/ptmini.exe;4 设定下载后文件被保存的路径,如果缺省,文件将被保存在当前目录下。lprInfo-strSaveBasePath=d:;5 创建一个PTask对象,准备开始一个新的任务。PTask* pTask=new PTask();6 设定启动多少个线程同时下载。pTask-SetMaxThreadNo(10);7 将PRECVINFO结构的地址赋给PTask对象。pTask-m_lprRecvInfo=lprInfo;8 开始执行一个HTTP下载任务。pTask-StartTask(TASK_HTTP_RECV);任务在执行过程中会向PDefine:rSMsgInfo结构中定义的窗体发送消息,以表明当前的任务执行状态。任务结束后,窗体也会接收到消息以表明当前任务是否已经完成。关于这些消息的说明,请查阅PDefine.h中的消息的说明。 八 建立一个语音聊天想实现自己的IPPhone吗?想和你在国外的朋友互诉一下衷肠吗?不用再担心昂贵的国际长途费用,写个小的程序,一切就OK啦。你会发现,使用PPQ.DLL实现一个语音聊天非常简单。1 开始一个聊天任务,其中this-m_pFriend是一个已经创建好的PFriend对象。PTask* pTask=new PTask();pTask-m_pFriend=this-m_pFriend;pTask-StartTask(TASK_TCP_CHAT);2 启动声音播放设备PDefine:SPlaySound();3 初始化声音捕捉设备PDefine:SGetSoundCaptureDeviceList(NULL);PDefine:SInitSoundCaptureDevice(NULL);PDefine:SGetSoundCaptureAvailableFormats(NULL);PDefine:SCreateSoundCaptureBuffer(NULL);4 设置捕捉到的声音被传递给哪一个好友。PDefine:SSetSoundCaptureAcceptdFriend(this-m_pFriend);5 开始声音捕捉。PDefine:SRecordSound();经过以上的步骤,一个语音聊天已经被创建了,并且自动地开始捕捉声音,一旦有一个有效的声音被捕捉到,就会立即被传给指定的好友,接收到的声音被按照接收时的顺序排在一个队列中,声音播放设备会自动按照顺序播放。实际上,你已经可以同时和多人进行聊天,每个人都可以同时和你说话,但是在任意一个时刻你只能对其中一个人讲话。在集成IP组播以后,会提供方法,以实现同时将声音传递给多个好友。PPQ.DLL在语音的传输的实现上和其它程序实现语音传输的方式有很大的不同。大部分程序在实现语音传输时通常是启用2个TCP连接来完成(UDP方式除外),一个TCP连接用来传输控制命令或消息,一个TCP连接用来专门传输声音数据,因为它们的声音数据必需是连续传输的,即一旦启动语音聊天,即使你没有说话,也会有连续不断地数据被传送到连接方。PPQ.DLL通过一个简单的语音过滤功能,不再传送静音的数据,以减少不必要的数据传递量。另外,PPQ.DLL采用的是对象的传递方式,它只通过一个TCP连接来实现聊天,不管是文字聊天还是语音聊天,采用的都是同一个连接,你可以在聊天的过程中,一边进行语音聊天,一边通过聊天连接传送其它的数据,而彼此之间并不会互相干扰。 九 从另一个好友处下载一个文件通过在2个客户端之间建立一个连接,来完成指定文件的传送与接收,是P2P的基本功能。PPQ.DLL封装了整个过程,采用了多线程,断点续传的方式来实现文件的传送与接收,使处理标准和简单化。1 初始化开始一个传送或接收任务所必需的步骤LPPRECVINFO lprInfo=new PRECVINFO();memset(lprInfo,0,DWORD(&lprInfo-nPort)-(DWORD)lprInfo);lprInfo-strSaveBasePath=d:;PTask* pTask=new PTask();pTask-SetMaxThreadNo(5);pTask-m_lprRecvInfo=lprInfo;2 设定连接到哪一个好友,其中this-m_pFriend是一个已经创建好的PFriend对象。pTask-m_pFriend=this-m_pFriend;3 设定想下载的文件的数字标识pTask-m_dwFileID=100;4 开始一个通过TCP来接收文件的任务。pTask-StartTask(TASK_TCP_RECV);与好友之间的连接被自动地建立,并启动多线程来完成文件的接收。PPQ.DLL只有在连接被确定建立后,才会启动一个新的线程来接收数据,并不向FlashGet那样,只要有一个连接被建立,就会启动最大的线程个数,去偿试连接,结果经常是多个连接无法被建立,而线程却都被启动了,每个线程都在努力地偿试连接。PPQ.DLL在采用TCP和HTTP方式下载时,都遵循着这样一个原则:先偿试连接,等到连接被建立后才启动新的线程,等到开始传送有效数据后,才会去偿试进行下一个连接,以避免很多无效的线程被启动。 十PPQ.DLL的无关性协义传输PPQ.DLL的对象传送并不是MFC和JAVA的序列化对象,它使用了一套比MFC和JAVA更为先进的序列化对象的方式,在解码时不但可以正确地将传送时的对象还原出来,而且可以在传送的类无法识别的情况下,自动地还原成与传送的类最接近的一个基类的对象。PPQ.DLL的解码和编码程序,采用纯C+编写,可以很容易地改写成其它语言,整个解码和编码过程不需要任何的语法分析,也不用对数据进行扫描,所有编码和解码过程采用顺序执行过程,执行速度非常快,而且整个的编码和解码程序编译后只有几K大小。 在开发PPQ.DLL的初期,只是为了将P2P的具体连接过程和传输数据的过程封装起来,以简化P2P的开发,并且使彼此开发的程序,可以在自定义传输协议的情况下互相通信,它的基本思路是采用对象作为基本信息单位来传递。TCP采用的是一种流式的数据传送方式,因此对于接收方来讲,在接收有效数据之前,必需明确地接收一些数据,来表明其后的有效数据所表示的意义,这里暂且把表明其后有效数据意义的数据,称作指令,把指令后所传送的有效数据称为值,可以看出,实际的流式数据是由指令和值来构成的。指令和值一起才能够明确地表示出数据的有效意义,没有指令的数据,实际是无效的,因为无法明确地知道它所表示的意义。指令和值可以重复出现多次,并且值由字节构成,每个字节由8位二进制来表式,其长度可以是任意的,没有限制。一个或一组指令和值组合在一起,就构成了指令对象。重复出现的一个或一组指令对象可以明确地表明希望接收方去完成某一种操作,这些指令对象和要完成的操作一起构成了一个事务,所以TCP的应用实际是一种基于事务的处理。 MFC和JAVA都提供了非常完善的序列化对象方式,但可惜的是,彼此之间无法互用,MFC的对象只能由MFC来解析,JAVA也是一样,因此,要想实现跨平台操作,就不能使用它们的序列化对象方式。SOAP和XML也是一种很好地与平台无关的传输协义,来标准化数据传送时的格式,但它们都是对字符串来进行操作,这也并不符合TCP传输二进制流的概念。 如果将传送数据作为字符串来表示,就不得不考虑不同平台的字符编码问题,但是这种考虑与实际的数据传送是相违背的,因为传送的数据实际都是以二进制字节来传送的。为了将传送数据以二进制字节方式来传送,PPQ.DLL重新定义了一套序列化对象的方式,在序列化对象时,将对象转变成二进制流来传送,在反序列化时,直接将二进制流拷贝到对象相应的属性的缓冲区中,而不再以字符串的形式来出现,避开了不同平台对字符编码的问题。PPQ.DLL的序列化和反序列化对象时,无需定义任何的语法规则,也没有定义任何的不可用字符,所有的数据均是以字节为单位来传送和接收,在反序列化对象时,不需要对接收数据进行任何的扫描,也没有使用循环,所有操作均是顺序完成,指令形成速度非常快,并且可以自动探测并丢弃未知指令对象和错误的指令对象,即使接收数据中间出现错误,仍然能够跳过错误的数据,正确地接收后续的指令对象。将TCP的流式数据作为事务来处理的最大好处是,可以用一个DLL、OCX或COM等组件来封装一个或多个事务的具体处理过程,所有的事务处理都是基于指令对象来进行的处理,而不用去追究数据的来源。封装后的事务可以直接被其他的开发者调用,而不需要再为处理相同的事务去重复开发程序,能更好地加快开发过程,减少错误发生的机率。这是PPQ.DLL的一个宗旨。 PPQ.DLL本身并没有规定连接双方应该传送的指令对象,它采用插件的形式,支持外部挂接任意多组指令对象,交由PPQ.DLL处理的数据会被PPQ.DLL自动解析成指令对象,但是哪一些指令对象是开发者需要的,却是由开发者自己来定义的。只有开发者规定的指令对象,PPQ.DLL才会将指令对象提交给相应的指令对象的处理程序,对于不可识别的指令对象,PPQ.DLL会自动地丢弃。PPQ.DLL的序列化对象与MFC和JAVA的序列化对象的最大不同点在于,MFC和JAVA的序列化对象只能将对象还原成原来保存的类的对象,即如果原来保存的类不存在,则反序列化时会失败,并抛出异常。PPQ.DLL的序列化对象在反序列化过程中,会自动分析数据流所表示的类是否可以识别,如果不能识别,则会查找该类的基类,找到一个与数据流所表示的类最为接近的一个基类,然后还原成该基类的一个对象,调用该基类对象的指令处理程序处理该指令,派生类中的多余的不可识别的数据会被自动丢弃。 PPQ.DLL的反序列化方式是进行无关性协义传输的一个关键。 让我们分析一下互联机器进行数据通讯的过程。以HTTP信息头为例,在HTTP协议中规定HTTP的头可以包含任意多行信息,每一行之间用rn结束,连续的2个rn表示整个HTTP信息头结束,其后紧接着为有效数据。在HTTP的信息头中,有一部分是每一个HTTP信息头都必需包含的信息,如HTTP标志,版本号,返回代码等,这个公共部分实际上就是一个基准的类。HTTP信息头对于不同的服务器来讲,它是允许扩充的,可以加入一些对于该服务器能够解析的其它标志,来指示服务器采取一些特定动作,这实际是对原基准类的一个扩充,相当于原基准类的一个派生类。一个用户传递了一个派生类对象,服务器在接收到派生类对象时,如果它能够识别这个派生类,表示它需要根据这个派生类来执行一些特定的操作,则在反序列化时,会创建出这个派生类的对象,通知服务器。如果服务器不识别这个派生类对象,在反序列化时,会自动地查找该服务器可以识别的该类的一个最接近的基类,这个基类中所保存的数据将是这个服务器所关心的数据,DLL会创建出这个基类,然后通知服务器。 PPQ.DLL的优势在什么地方呢?HTTP和XML等协议,其传递的都是字符串,接收方需要去解析字符串,找到自己感兴趣的标识,再次分解字符串,得到指定的值。每一个接收方都必需去实现这个过程,当然我们可以使用XML语法解析器将XML造型成对象来处理。让我们关注一下XML造型成对象的过程,就会明显地感受到它与PPQ.DLL的反序列化对象的本质区别。HTTP和XML必需同时传递属性名称和属性的值,因为接收方在解析对象时,实际并不知道原来传递的内容是什么,它只是将属性名称和值保存在哈希表中,属性名相当于哈希表的一个键,而属性的值相当哈希表中该键的值。当接收方访问属性时,实际是在哈希表中搜索指定的键,然后返回给用户该键所表示的值。从这里面,我们可以看出这样一个问题,接收方必需知道键的正确含义,否则它无法得到该键所表示的值。即然接收方已经知道了键,那么为什么还需要去传递这个键呢?答案很简单,如果不传递键,它无法区分值应该对应到哪一个键。我们再看一下PPQ.DLL是如何反序列化对象的。即然键对于接收方来讲是已知的,它当然可以作为对象中的一个属性来存在,这和XML解析器将XML转变成XML对象是一个道理。每一个XML的语法都可以作为一个指令类或一个指令类的派生类,而XML的属性相当于类中的一个属性,使用PPQ.DLL可以直接传递这个指令对象,PPQ.DLL序列化时并没有传递属性的名称,它只把类作为一个整体来传递,而类对象的解析过程是由类自己来定义的,因此,它仍然能够被完整地解析出来。通过PPQ.DLL反序列化出来的类对象是传送方传递的类或基类对象的原形,它不但包含了属性的值,并且也同时包含了与该对象相关的一切方法。我们在创建相关的协义规则时,也同时制定了应该如何解析该规则,XML和HTTP都只是传输了规则,却无法传输规则的解析方法,而且这些规则必需是公开规定的。而通过指令对象的传递,不但可以传递规则,而且同时也传递了解析该规则的方法,并且还能够通过完全地封装一个或几个指令对象,来完全地封装起规则,只对外提供访问的接口。 HTTP和XML等协义仍然需要一定的语法规则,在书写时也必需按照该规则来书写,而PPQ.DLL的对象传递是一种真正地无关性协义,它没有任何的语法规则来限制。 让我们再看一下PPQ.DLL为团队开发所带来的便利。在传统的团队开发模式中,双方必需预先制定好要传输的协义规则,然后开始各自编写程序,如果一方需要改变或增加新的传输规则,他必需要通知其他的开发者,这个协议已经改变啦,你必需要相应地改变解码程序。但是如果采用了PPQ.DLL的对象传送,即使有任何一方改变了传输规则,也不用互相通知,因为解码程序不需要改变,而且PPQ.DLL的宗旨是封装,它强调将任务划分成若干指令来完成,各个指令的组合用来完成不同的任务,而各指令的实现功能可以被完全地封装在指令内部,与指令的交互,只是通过接口来完成。 传输指令对象的好处是很多的,无法在这里一一例举出来,它是对传统标准制定方式的一种挑战,使用这种方式,使所有的开发者都可以参与到标准的制定过程中,而且这种标准就象滚雪球一样,会在自然地使用过程中变得越来越庞大,越来越规范,越来越充实,每一个开发者都不必再从最底层作起,他们可以从前人的基础之上直接继承或派生出新的应用,以最快地速度开发出自己的程序。十一 PPQ.DLL的回调(钩子)函数说明* 函数名称:*typedef PBaseAct* (WINAPI *GOCALLBACK)(LPCTSTR lpszClassID)*参数:*LPCTSTRlpszClassID-唯一标识一个类的ID。*返回值:*PBaseAct*-返回新创建的对象。*说明:*这是一个钩子函数。通过这个函数将得到用户自定义的PBaseAct派生类的一个实例。注意:这是一个钩子函数,每一次的设定,都会被记录下来。v1.02版以后,对算法进行了改进,不再按照顺序来逐个调用所设定的钩子函数,钩子函数的执行和安装顺序没有直接关系,DLL会直接调用处理该ClassID的钩子函数。可以在一个钩子函数中同时处理多个ClassID,每一个ClassID都必需公布,并且明确各诉哪些ClassID是必需的,是完成同一个任务,哪些是完成另一个任务所必需的,哪一些是可有可无的。这样其他开发者在设置钩子函数时,才能够根据自己的需要来决定应该使用哪些类。举例如下,其中Self1Act是自己定义的PBaseAct的派生类;USelf1Act是其它开发者定义的PBaseAct的派生类,本地必需有这两个类的声明。PBaseAct* WINAPI GlobalFunUserGetObject(LPCTSTR lpszClassID)if(memcmp(lpszClassID,B6FFC24C-7E13-11D0-9B47-00C04FC2F51D,PPQ_CLASS_ID_LEN)=0)/如果是自己定义的对象。return new Self1Act();else if(memcmp(lpszClassID,A9BEDC36-7E13-11D0-9B47-00C04FC2F51D,PPQ_CLASS_ID_LEN)=0)/加入对其他用户创建的对象的支持。return new USelf1Act();return NULL;关于用户自定义对象的健状性问题与恶意性攻击的解决办法:如果你但心其他用户会发送一个非法的对象,但是使用了在你在函数中规定的ClassID,你大可不必担心。DLL通过以下两种方法来防止这种恶意攻击行为:1当双方建立连接的时候,都必需通过一个身份验证的过程,这个过程中双方传递的的指令对象是内部定义好的指令对象,而且整个过程是外部不可干预的,只有通过身份验证的双方才会建立起连接,也就是说,建立连接的双方都是相互信任的。2如果通过身份验证的连接方要进行恶意攻击,DLL还会通过第二种办法自动丢弃这些错误的指令,绝对不会造成程序的非法操作。DLL在发现恶意性攻击时,会记录下攻击的次数,当攻击次数超过一定数量时,会向用户发出警告,告诉用户发出恶意攻击的连接方的ID,并自动断开该连接。* * * * * * * * * * * * *函数名称:* typedef PFriend* (WINAPI* GETPALCALLBACK)(LPCTSTR lpszFriendID)*参数:* LPCTSTR lpszFriendID -好友的ID标识*返回值:* PFriend* -指向好友对象的指针。*说明:* 根据传递的好友ID返回指向具有该ID的PFriend对象的指针。* * * * * * * * * * * * *函数名称:* typedef void (WINAPI *GETFILENCALLBACK)(DWORD dwFileID,PFriend* pFriend,CString* pstrFileN)*参数:* DWORD dwFileID -请求的文件的数字标识。* PFrined* pFriend -指向请求该文件的好友对象的指针。* CString* pstrFileN -指向保存文件数字标识所对应的实际文件名的指针。*返回值:* 无。*说明:* 该函数将根据传递的dwFileID,来得到实际所对应的文件名。文件名保存在pstrFileN对象中。 如果函数执行后*pstrFileN=,表示获取实际文件失败。 可以在这个回调函数中对文件编号进行校验,决定好友是否有权得到该文件。 声明: 对于文件采用数字标识来表示,其最主要的目的是为了安全性,以及将来的扩展。 数字标识如何与实际的文件名相对应,可以采用很多种办法,因此并没有包含在 这个DLL中。 关于数字标识与实际文件名的对应关系,将提供一个专门的类来实现,这只是一种 解决办法,大家可以自己去偿试采用更好的办法来解决这个问题。 下面是一种建立数字标识与实际文件名的对应关系的方式: 采用数据库中记录的存储方式来保存每一个数字标识与实际文件名的对应关系,每 一个数字标识与实际文件名的对应关系相当于一条记录,数据被集中保存在一个文 件中,每一个记录均是定长的,48个字节。 因为数字标识所表示的文件可以是本地机器上的任何一个目录下的任何一个

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论