📄 dsp_sdk_.txt
字号:
DSP v1.0--序列化和反序列化对象和DNS v1.0--得到域的邮件服务器
分类: 网络SDK开发包
作者姓名: 王浩
邮件地址: wanghao0727@sohu.com
作者相关信息: 热爱编程,尤其是P2P和网络方面的编程
程序下载 见附件
开发环境: VC6 Windows 2000
测试环境: Windows 2000 WindowsXP 2000Server
更新记录:
使用许可:可以以任何形式传播、使用DSP以DLL形式发布的SDK开发包,在未正式公布原代码前,严禁反编译或抄袭原代码
DSP序列化反序列化对象SDK开发包
DSP(Dynamic Serialize Packet)是一个动态序列化和反序列化对象的SDK开发包,使用DSP可以将对象序列化成数据流保存到文件中,或者将序列化后的数据流通过Socket传递给远端;也可以使用DSP从文件或Socket中读取数据,然后反序列化成对象。
DSP和VC++的序列化、Java的序列化有着本质的区别,比VC++和Java的序列化对象具有更好的控制性,DSP提供了对象标准的序列化方式,可以将对象的数据以数据流的方式传递,不管发送方是Java还是C++,也不论接收方是C++还是Java,或是其它的语言,数据流都可以被正确地还原成相应的对象。(当前的DSP采用纯C++语言开发,以后将陆续地提供其它语言的SDK开发包,在适当地时候,我会提供所有的源代码)
DSP在反序列化对象时,可以反序列化数据流成为序列化时的对象,如果序列化时的对象注册过,则可以将数据流反序列化成序列化对象的最接近的一个基类。
DSP采用阻塞方式序列化和反序列化对象,实时地传送或接收序列化后的数据到Socket或文件中,不需要经过缓冲区拷贝,大大地提高了序列化和反序列化的速度。
DSP采用二进制数据流方式序列化数据,允许序列化后的数据中包含字符串终结符'\0',因此允许序列化任意的二进制数据、文件、图像缓冲区、音频缓冲区等。
DSP可以传送任意大小的数据,你甚至可以在一个对象中包含一个或多个任意大小的二进制文件,DSP会自动地对数据进行分段传送,并确保数据能正确地被序列化。利用DSP可以序列化任意大小文件的特性,你可以在序列化对象时读取一个文件,通过Socket传送到远端;远端读取Socket数据,在反序列化数据流时,直接将传送的文件保存起来,从而实现P2P或Email中传送多媒体信息的应用。
DSP可以在序列化对象时选择是否进行CRC校验、是否对数据值进行压缩处理,可以自定义压缩处理函数,并且可以指定反序列化对象后自动执行的函数集。
DSP通过多重CRC校验,保证数据不会在传送过程中被修改,为保证数据的安全性,每一类序列化对象都可以自定义压缩处理函数,在压缩处理函数内对数据进行压缩或加密,如果设定了压缩处理函数,DSP会在序列化过程中调用压缩处理函数对数据进行处理,传递压缩函数处理过后的数据;在反序列化过程中,DSP就会调用解压缩处理函数,先将接收到的数据还原,然后将数据保存到对象的相应属性中。
DSP还允许从Socket或文件中读取数据到一个已存在的指定对象中,从而确保只能从数据源得到指定的对象。
DSP可以处理任意多层嵌套对象的序列化和反序列化,即一个可序列化对象可以是另一个可序列化对象的一个属性,并且一个可序列化对象中可以包含任意多个可序列化对象。
DSP反序列化时,对象中的任何一个属性的值被反序列化完成后,都会发出明确的通知,可以在接到该通知后执行任意的代码。
SDK开发包的使用说明
SDK包的内容?
SDK包仅仅包含2个类,一个是DSP类,该类中定义了序列化和反序列化对象时的方法,以及所需要的结构,DSP类不能够被实例化,所有的方法都是静态的,DSP类的实际作用仅仅是定义一个命名空间。
DSP类中包含有两个结构,_DSPPACKET和_DSPERROR。_DSPPACKET结构是序列化和反序列化时必不可少的结构,在序列化和反序列化时需要创建一个该结构的实例,然后调用结构中的方法进行序列化和反序列化操作。序列化操作的WriteObject()方法和反序列化的ReadObject()方法都是该结构中的方法。
_DSPERROR结构中记录了最近一次错误的代码,错误的详述,以及在序列化和反序列化第几个基类的第几个属性时产生了错误。如果调用ReadObject()和WriteObject()返回了一个错误,可以调用_DSPPACKET::GetLastError()返回描述该错误的_DSPERROR结构的指针。
SDK包中的另一个类是DSPACT类,这个类是所有可以被序列化和反序列化的类的基类。
这两个类全部都是采用纯C++语言书写的。
SDK包的附带内容?
SDK包中还带有一个DNS类,该类的主要功能是查询DNS服务器,得到相关的信息,这个类还在完善中。
该类提供了一些较低级的方法来查询DNS服务器,也封装了一个较高级的方法DNS::_DNSPACKET::GetMXHostSet(),该方法会直接查询DNS服务器,并返回包含MX记录的集合,然后可以直接调用另一个较高级的方法DNS::_DNSPACKET::GetMX()得到一个MX记录,重复调用该函数,就可以得到下一个MX记录,一直到读完为止。
这个DNS类比MicroSoft SDK开发包中提供的DnsQuery()方法要简单的多,你只需要创建一个DNS::_DNSPACKET结构的实例,然后调用该实例的GetMXHostSet()方法,传递要查询的域名即可,得到MX记录也只需要调用该实例的GetMXHost()方法,该方法会返回要查询的域名的邮件服务器的hostent结构的指针。
什么对象可以被序列化?
由DSPACT类派生出来的任何一个类,或者说只要一个类的基类是DSPACT类,这个类就可以被序列化。就象VC++的所有可以被序列化的类必需是由CObject类派生出来的,DSP可以被序列化的类也必需是由类DSPACT派生出来的。
什么对象可以被反序列化?
任何由DSPACT类派生出来的类都可以被DSP反序列化,被反序列化的类可以预先调用DSP::RegisterAct()函数注册该类,这样,DSP在反序列化过程时可以动态创建出被注册过的类的对象;如果类没有被注册过,也可以通过在反序列化时传递需要被反序列化的对象的指针,将数据反序列化到指定的对象中。
如何对反序列化对象上溯造型?
反序列化对象是通过调用ReadObject()函数来实现的,函数返回的是指向反序列化后的对象的指针,该指针固定是一个DSPACT对象的指针,如何知道该指针应该上溯造型成哪一个对象的指针呢?可以通过调用DSPACT对象的IsKindOf()方法,传递类名字的字符串指针,该函数会判断该对象是否是指定的类的一个对象,并返回true或false。如果方法返回true,则对象可以被安全地上溯造型为指定的对象。
在调用DSP::RegisterAct()方法注册类时,可以传递一个附加的32位数据值,该值可以是一个结构的指针,也可以是一个DWORD数据(在Window系统中,可以设定成消息的ID)。当对象被反序列化成功后,会返回一个DSPACT对象的指针,这时在_DSPPACKET结构中的属性dwData中保存了该值。
DSP类定义
#include <string>
#include <fstream.h>
#include <deque>
#include <math.h>
#ifndef AFX_EXT_CLASS
#define AFX_EXT_CLASS
#endif
#include "StdAfx.h"
#define SECT_MAX_SIZE 0xFFF //分段传送时段的最大尺寸
class AFX_EXT_CLASS DSPACT;
//在所有的DSPACT派生类的头文件中必需包含的宏定义
#define SELF_SERIALIZE(classid,className,base_className) \
public: \
virtual char* GetClassID() {return classid;} \
virtual bool IsKindOf(char* lpClassName){return (::strcmp(className,lpClassName)==0);}\
protected: \
virtual BYTE GetClassLevel() {return (base_className::GetClassLevel()+1);} \
//返回DSPPACT派生类对象的函数的指针
#define DSPGETOBJFUNC(varN) DSPACT* (*varN)(const std::string& strID)
#define CASTDSPGETOBJFUNC DSPACT* (*)(const std::string& strID)
//缓冲区分段接收函数的指针
#define DSPSECTRECV(varN) bool (*varN)(const char* const lpBuff,int nBuffLen,bool bLast)
#define CASTDSPSECTRECV bool (*)(const char* const lpBuff,int nBuffLen,bool bLast)
//缓冲区分段传送函数的指针
#define DSPSECTSEND(varN) bool (*varN)(char** const lpBuff,int& nBuffLen,bool& bContinue)
#define CASTDSPSECTSEND bool (*)(char** const lpBuff,int& nBuffLen,bool& bContinue)
//压缩函数的指针
#define DSPCOMPRESSFUNC(varN) bool (*varN)(char** const lpBuff,int& nBuffLen)
#define CASTDSPCOMPRESSFUNC bool (*)(char** const lpBuff,int& nBuffLen)
//解压缩函数的指针
#define DSPUNCOMPRESSFUNC(varN) bool (*varN)(char** const lpBuff,int& nBuffLen,bool bStart)
#define CASTDSPUNCOMPRESSFUNC bool (*)(char** const lpBuff,int& nBuffLen,bool bStart)
class AFX_EXT_CLASS DSP
{
public:
struct AFX_EXT_CLASS _DSPPACKET;
public:
enum _DSPERRTYPE
{
ERR_RECV_HEADER =10000,
ERR_FIND_HEADER,
ERR_RECV_ATTRHEADER,
ERR_VERIFY_ATTRHEADER,
ERR_RECV_CLASSID,
ERR_NOTGET_DSPACT,
ERR_RECV_ATTRSIZE,
ERR_SET_ATTR_BUFF,
ERR_UNCOMPRESS,
ERR_RECV_ATTR_SECT,
ERR_RECV_ATTRVALUE,
ERR_RECV_PACKETCRC,
ERR_RECV_PACKET_CRC,
ERR_RECV_NAME,
ERR_SEND_HEADER =11000,
ERR_SEND_ATTRHEADER,
ERR_SEND_CLASSID,
ERR_SERIALIZE_ATTR,
ERR_SEND_ATTR_SECT,
ERR_SEND_ATTRSIZE,
ERR_SEND_ATTRVALUE,
ERR_SEND_PACKETCRC,
ERR_SEND_NAME,
ERR_COMPRESS,
};
struct AFX_EXT_CLASS _DSPERROR
{
BYTE byClassLevel; //类深度
DWORD dwAttrNo; //属性个数编号
int nErrorNo; //错误代码
std::string strErrDetail; //错误描述
};
struct AFX_EXT_CLASS _DSPPACKET
{
//DSP包结构
timeval Timeout; //接收Socket时的超时时间
DWORD dwData; //在注册类时指定的该类的附加数据
bool& bKeepRun; //是否继续运行,通过这个布尔变量,可以随时中止序列化或反序列化过程
public:
_DSPPACKET(bool& bRun):bKeepRun(bRun),dwAttrSize(0){Timeout.tv_sec=10;Timeout.tv_usec=0;};
inline void Empty()
{
pDspAct =NULL;
dwAttrSize =0;
wPacketCRC =0;
};
inline _DSPERROR* const GetLastError(){return &LastError;};
void SetParameter(bool bCompress=false,bool bVerifyCRC=true,BYTE byInitType=0);
bool IsVerifyCrc();
bool IsCompress();
DSPACT* ReadObject(char* lpUDPBuff,int nUDPBuffLen,DSPACT* pAct=NULL);
DSPACT* ReadObject(SOCKET sock,DSPACT* pAct=NULL);
DSPACT* ReadObject(ifstream& ifs,DSPACT* pAct=NULL);
bool Read(char& attr);
bool Read(BYTE& attr);
bool Read(short& attr);
bool Read(WORD& attr);
bool Read(int& attr);
bool Read(DWORD& attr);
bool Read(bool& attr);
bool Read(std::string& attr,DWORD dwLen);
bool Read(char* const pAttr,DWORD dwLen);
bool Read(DSPACT& attr);
inline bool WriteObject(SOCKET sock,sockaddr_in& to,char* const lpUDPBuff,int nUDPBuffLen,DSPACT& act);
bool WriteObject(SOCKET sock,sockaddr_in& to,int nUDPSize,DSPACT& act);
bool WriteObject(SOCKET sock,DSPACT& act);
bool WriteObject(ofstream& ofs,DSPACT& act);
void Write(int attr);
void Write(DWORD attr);
void Write(bool attr);
void Write(const std::string& attr);
void Write(char* const pAttr,DWORD dwLen,BOOL bLast=TRUE);
void Write(DSPACT& attr,bool bCompress=false,bool bVerifyCRC=true,BYTE byInitType=0);
#ifndef UNIX_SYSTEM_
void Write(const CString& attr);
bool Read(CString& attr,DWORD dwLen);
bool Serialize(const CString& strValue,const char* lpName=NULL,BYTE nNameLen=0);
bool UnSerialize(CString& strValue);
#endif
void SerializeStart(ofstream& ofs,DSPCOMPRESSFUNC(pFun)=NULL);
bool Serialize(int nValue,const char* lpName=NULL,BYTE nNameLen=0);
bool Serialize(BYTE byValue,const char* lpName=NULL,BYTE nNameLen=0);
bool Serialize(bool bValue,const char* lpName=NULL,BYTE nNameLen=0);
bool Serialize(std::string& strValue,const char* lpName=NULL,BYTE nNameLen=0);
bool Serialize(char* lpBuff,int nBuffLen,const char* lpName=NULL,BYTE nNameLen=0,DSPSECTSEND(pFunc)=NULL);
bool Serialize(DSPACT& act,const char* lpName=NULL,BYTE nNameLen=0);
bool SerializeEnd();
bool UnSerializeStart(ifstream& ifs,DSPUNCOMPRESSFUNC(pFun)=NULL);
inline BYTE IsKinkOf(std::string& strName);
inline bool UnSerialize(DWORD& value,int& nValueLen);
bool UnSerialize(int& nValue);
bool UnSerialize(DWORD& dwValue);
bool UnSerialize(short& sValue);
bool UnSerialize(WORD& wValue);
bool UnSerialize(char& cValue);
bool UnSerialize(BYTE& byValue);
bool UnSerialize(std::string& strValue);
bool UnSerialize(char* pValue,int* nValueLen);
};
static bool RegisterAct(const char* classID,DSPGETOBJFUNC(dspActFun),DWORD dwData=0);
static SOCKET ConnectTo(const char *lpSrvName,int nSrvPort,bool bInternet=true,int nRetryCount=5);
static SOCKET GetUDPSocket(int nListenPort=-1,bool bInternet=true);
static SOCKET GetTCPSocket(int nListenPort=-1,bool bInternet=true);
static bool GetAddrByName(const char *lpName,WORD port,sockaddr_in& addr);
static void GetAddrByIP(const char *lpIP,WORD port,sockaddr_in& addr,bool bInternet=true);
static int WaitRecvUDP(SOCKET sock,char *lpUDPBuff,int nUDPBuffLen,struct sockaddr_in& from,int nTimeoutSec=30);
static DWORD GetFileSize(const char* lpFilename);
static DWORD CreateNullFile(const char* lpFilename,int nSize,bool bAppend=true);
static void SafeRelease();
static inline BOOL OpenIfstreamForRead(ifstream& ifs,const char* const lpFileName,int nMode=0,int nShareMode=filebuf::openprot)
{ ifs.open(lpFileName,ios::in|ios::binary|ios::nocreate|nMode,nShareMode);
return ifs.is_open();
};
static inline BOOL OpenOfstreamForWrite(ofstream& ofs,const char* const lpFileName,int nMode=0,int nShareMode=filebuf::sh_write||filebuf::sh_read)
{ ofs.open(lpFileName,ios::out|ios::binary|nMode,nShareMode);
return ofs.is_open();
};
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -