?? 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);
};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -