?? dsp_sdk_.txt
字號:
DSP v1.0--序列化和反序列化對象和DNS v1.0--得到域的郵件服務(wù)器
分類: 網(wǎng)絡(luò)SDK開發(fā)包
作者姓名: 王浩
郵件地址: wanghao0727@sohu.com
作者相關(guān)信息: 熱愛編程,尤其是P2P和網(wǎng)絡(luò)方面的編程
程序下載 見附件
開發(fā)環(huán)境: VC6 Windows 2000
測試環(huán)境: Windows 2000 WindowsXP 2000Server
更新記錄:
使用許可:可以以任何形式傳播、使用DSP以DLL形式發(fā)布的SDK開發(fā)包,在未正式公布原代碼前,嚴(yán)禁反編譯或抄襲原代碼
DSP序列化反序列化對象SDK開發(fā)包
DSP(Dynamic Serialize Packet)是一個動態(tài)序列化和反序列化對象的SDK開發(fā)包,使用DSP可以將對象序列化成數(shù)據(jù)流保存到文件中,或者將序列化后的數(shù)據(jù)流通過Socket傳遞給遠(yuǎn)端;也可以使用DSP從文件或Socket中讀取數(shù)據(jù),然后反序列化成對象。
DSP和VC++的序列化、Java的序列化有著本質(zhì)的區(qū)別,比VC++和Java的序列化對象具有更好的控制性,DSP提供了對象標(biāo)準(zhǔn)的序列化方式,可以將對象的數(shù)據(jù)以數(shù)據(jù)流的方式傳遞,不管發(fā)送方是Java還是C++,也不論接收方是C++還是Java,或是其它的語言,數(shù)據(jù)流都可以被正確地還原成相應(yīng)的對象。(當(dāng)前的DSP采用純C++語言開發(fā),以后將陸續(xù)地提供其它語言的SDK開發(fā)包,在適當(dāng)?shù)貢r候,我會提供所有的源代碼)
DSP在反序列化對象時,可以反序列化數(shù)據(jù)流成為序列化時的對象,如果序列化時的對象注冊過,則可以將數(shù)據(jù)流反序列化成序列化對象的最接近的一個基類。
DSP采用阻塞方式序列化和反序列化對象,實時地傳送或接收序列化后的數(shù)據(jù)到Socket或文件中,不需要經(jīng)過緩沖區(qū)拷貝,大大地提高了序列化和反序列化的速度。
DSP采用二進(jìn)制數(shù)據(jù)流方式序列化數(shù)據(jù),允許序列化后的數(shù)據(jù)中包含字符串終結(jié)符'\0',因此允許序列化任意的二進(jìn)制數(shù)據(jù)、文件、圖像緩沖區(qū)、音頻緩沖區(qū)等。
DSP可以傳送任意大小的數(shù)據(jù),你甚至可以在一個對象中包含一個或多個任意大小的二進(jìn)制文件,DSP會自動地對數(shù)據(jù)進(jìn)行分段傳送,并確保數(shù)據(jù)能正確地被序列化。利用DSP可以序列化任意大小文件的特性,你可以在序列化對象時讀取一個文件,通過Socket傳送到遠(yuǎn)端;遠(yuǎn)端讀取Socket數(shù)據(jù),在反序列化數(shù)據(jù)流時,直接將傳送的文件保存起來,從而實現(xiàn)P2P或Email中傳送多媒體信息的應(yīng)用。
DSP可以在序列化對象時選擇是否進(jìn)行CRC校驗、是否對數(shù)據(jù)值進(jìn)行壓縮處理,可以自定義壓縮處理函數(shù),并且可以指定反序列化對象后自動執(zhí)行的函數(shù)集。
DSP通過多重CRC校驗,保證數(shù)據(jù)不會在傳送過程中被修改,為保證數(shù)據(jù)的安全性,每一類序列化對象都可以自定義壓縮處理函數(shù),在壓縮處理函數(shù)內(nèi)對數(shù)據(jù)進(jìn)行壓縮或加密,如果設(shè)定了壓縮處理函數(shù),DSP會在序列化過程中調(diào)用壓縮處理函數(shù)對數(shù)據(jù)進(jìn)行處理,傳遞壓縮函數(shù)處理過后的數(shù)據(jù);在反序列化過程中,DSP就會調(diào)用解壓縮處理函數(shù),先將接收到的數(shù)據(jù)還原,然后將數(shù)據(jù)保存到對象的相應(yīng)屬性中。
DSP還允許從Socket或文件中讀取數(shù)據(jù)到一個已存在的指定對象中,從而確保只能從數(shù)據(jù)源得到指定的對象。
DSP可以處理任意多層嵌套對象的序列化和反序列化,即一個可序列化對象可以是另一個可序列化對象的一個屬性,并且一個可序列化對象中可以包含任意多個可序列化對象。
DSP反序列化時,對象中的任何一個屬性的值被反序列化完成后,都會發(fā)出明確的通知,可以在接到該通知后執(zhí)行任意的代碼。
SDK開發(fā)包的使用說明
SDK包的內(nèi)容?
SDK包僅僅包含2個類,一個是DSP類,該類中定義了序列化和反序列化對象時的方法,以及所需要的結(jié)構(gòu),DSP類不能夠被實例化,所有的方法都是靜態(tài)的,DSP類的實際作用僅僅是定義一個命名空間。
DSP類中包含有兩個結(jié)構(gòu),_DSPPACKET和_DSPERROR。_DSPPACKET結(jié)構(gòu)是序列化和反序列化時必不可少的結(jié)構(gòu),在序列化和反序列化時需要創(chuàng)建一個該結(jié)構(gòu)的實例,然后調(diào)用結(jié)構(gòu)中的方法進(jìn)行序列化和反序列化操作。序列化操作的WriteObject()方法和反序列化的ReadObject()方法都是該結(jié)構(gòu)中的方法。
_DSPERROR結(jié)構(gòu)中記錄了最近一次錯誤的代碼,錯誤的詳述,以及在序列化和反序列化第幾個基類的第幾個屬性時產(chǎn)生了錯誤。如果調(diào)用ReadObject()和WriteObject()返回了一個錯誤,可以調(diào)用_DSPPACKET::GetLastError()返回描述該錯誤的_DSPERROR結(jié)構(gòu)的指針。
SDK包中的另一個類是DSPACT類,這個類是所有可以被序列化和反序列化的類的基類。
這兩個類全部都是采用純C++語言書寫的。
SDK包的附帶內(nèi)容?
SDK包中還帶有一個DNS類,該類的主要功能是查詢DNS服務(wù)器,得到相關(guān)的信息,這個類還在完善中。
該類提供了一些較低級的方法來查詢DNS服務(wù)器,也封裝了一個較高級的方法DNS::_DNSPACKET::GetMXHostSet(),該方法會直接查詢DNS服務(wù)器,并返回包含MX記錄的集合,然后可以直接調(diào)用另一個較高級的方法DNS::_DNSPACKET::GetMX()得到一個MX記錄,重復(fù)調(diào)用該函數(shù),就可以得到下一個MX記錄,一直到讀完為止。
這個DNS類比MicroSoft SDK開發(fā)包中提供的DnsQuery()方法要簡單的多,你只需要創(chuàng)建一個DNS::_DNSPACKET結(jié)構(gòu)的實例,然后調(diào)用該實例的GetMXHostSet()方法,傳遞要查詢的域名即可,得到MX記錄也只需要調(diào)用該實例的GetMXHost()方法,該方法會返回要查詢的域名的郵件服務(wù)器的hostent結(jié)構(gòu)的指針。
什么對象可以被序列化?
由DSPACT類派生出來的任何一個類,或者說只要一個類的基類是DSPACT類,這個類就可以被序列化。就象VC++的所有可以被序列化的類必需是由CObject類派生出來的,DSP可以被序列化的類也必需是由類DSPACT派生出來的。
什么對象可以被反序列化?
任何由DSPACT類派生出來的類都可以被DSP反序列化,被反序列化的類可以預(yù)先調(diào)用DSP::RegisterAct()函數(shù)注冊該類,這樣,DSP在反序列化過程時可以動態(tài)創(chuàng)建出被注冊過的類的對象;如果類沒有被注冊過,也可以通過在反序列化時傳遞需要被反序列化的對象的指針,將數(shù)據(jù)反序列化到指定的對象中。
如何對反序列化對象上溯造型?
反序列化對象是通過調(diào)用ReadObject()函數(shù)來實現(xiàn)的,函數(shù)返回的是指向反序列化后的對象的指針,該指針固定是一個DSPACT對象的指針,如何知道該指針應(yīng)該上溯造型成哪一個對象的指針呢?可以通過調(diào)用DSPACT對象的IsKindOf()方法,傳遞類名字的字符串指針,該函數(shù)會判斷該對象是否是指定的類的一個對象,并返回true或false。如果方法返回true,則對象可以被安全地上溯造型為指定的對象。
在調(diào)用DSP::RegisterAct()方法注冊類時,可以傳遞一個附加的32位數(shù)據(jù)值,該值可以是一個結(jié)構(gòu)的指針,也可以是一個DWORD數(shù)據(jù)(在Window系統(tǒng)中,可以設(shè)定成消息的ID)。當(dāng)對象被反序列化成功后,會返回一個DSPACT對象的指針,這時在_DSPPACKET結(jié)構(gòu)中的屬性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派生類對象的函數(shù)的指針
#define DSPGETOBJFUNC(varN) DSPACT* (*varN)(const std::string& strID)
#define CASTDSPGETOBJFUNC DSPACT* (*)(const std::string& strID)
//緩沖區(qū)分段接收函數(shù)的指針
#define DSPSECTRECV(varN) bool (*varN)(const char* const lpBuff,int nBuffLen,bool bLast)
#define CASTDSPSECTRECV bool (*)(const char* const lpBuff,int nBuffLen,bool bLast)
//緩沖區(qū)分段傳送函數(shù)的指針
#define DSPSECTSEND(varN) bool (*varN)(char** const lpBuff,int& nBuffLen,bool& bContinue)
#define CASTDSPSECTSEND bool (*)(char** const lpBuff,int& nBuffLen,bool& bContinue)
//壓縮函數(shù)的指針
#define DSPCOMPRESSFUNC(varN) bool (*varN)(char** const lpBuff,int& nBuffLen)
#define CASTDSPCOMPRESSFUNC bool (*)(char** const lpBuff,int& nBuffLen)
//解壓縮函數(shù)的指針
#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; //屬性個數(shù)編號
int nErrorNo; //錯誤代碼
std::string strErrDetail; //錯誤描述
};
struct AFX_EXT_CLASS _DSPPACKET
{
//DSP包結(jié)構(gòu)
timeval Timeout; //接收Socket時的超時時間
DWORD dwData; //在注冊類時指定的該類的附加數(shù)據(jù)
bool& bKeepRun; //是否繼續(xù)運行,通過這個布爾變量,可以隨時中止序列化或反序列化過程
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();
};
};
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -