eMule分析之CEd2KLink类及其派生类分析

 

eMule分析之CEd2KLink类及其派生类分析

邵盛松2008年10月6日

CEd2KLink类主要功能是从ED2K链接字符串中找到需要连接主机.

CEd2KLink类派生出三个类分别是CED2KFileLink ,CED2KServerLink,CED2KServerListLink 

CED2KFileLink类的主要作用的从包含关键字file的字符串中的找到需要连接主机

CED2KServerLink类的主要作用的从包含关键字server的字符串中的找到需要连接主机

,CED2KServerListLink 类的主要作用的从包含关键字serverlist的字符串中的找到需要连接主机

类定义如下

class CED2KLink

{

public:

static CED2KLink* CreateLinkFromUrl(const TCHAR* url);

virtual ~CED2KLink();

typedef enum { kServerList, kServer , kFile , kInvalid } LinkType;

virtual LinkType GetKind() const = 0;

virtual void GetLink(CString& lnk) const = 0;

virtual class CED2KServerListLink* GetServerListLink() = 0;//下面是三个纯虚类

virtual class CED2KServerLink* GetServerLink() = 0;

virtual class CED2KFileLink* GetFileLink() = 0;

};

 

GetNextString函数用于截取字符串,

该函数具有多态性.都表示同一个功能这个给一个函数示例添加注释,

功能:截取字符串

参数说明:

rstr表示要操作的字符串

pszTokens表示需要查找的字符

riStart表示开始查找的位置

返回值

类型:CString

截取从riStart开始到所要查找的字符的位置之间的字符串(不包括所要查找的字符串)

CString GetNextString(const CString& rstr, LPCTSTR pszTokens, int& riStart)

{

CString strResult;

if (pszTokens != NULL && riStart != -1)//如果字符串不为空并且,开始查找数据的位置不是-1

{

int iToken = rstr.Find(pszTokens, riStart);

if (iToken != -1)//返回值为-1,表示没有查找到,iToken是所要查找数据的下标(从开始计算)

{

int iLen = iToken - riStart;

if (iLen >= 0)

{

strResult = rstr.Mid(riStart, iLen);//截取字符串从riStart开始,截取长度是iLen个

riStart += iLen + 1;

}

}

else

{

strResult = rstr.Mid(riStart);

riStart = -1;

}

}

return strResult;

}

:CreateLinkFromUrl函数注释

CED2KLink* CED2KLink::CreateLinkFromUrl(const TCHAR* uri)

{

/* 基本ed2k链接:       ed2k://|file|<文件名称>|<文件大小>|<文件哈希值>|/

   eD2k片段哈希值链接 ed2k://|file|<文件名称>|<文件大小>|<文件哈希值>|p=<片段哈希值>|/

   eD2k来源链接        ed2k://|file|<文件名称>|<文件大小>|<文件哈希值>|/|sources,<IP:端口>|/

   eD2k主机链接        ed2k://|file|<文件名称>|<文件大小>|<文件哈希值>|/|sources,<主机名称:端口>|/

   eD2kHTTP 来源链接   ed2k://|file|<文件名称>|<文件大小>|<文件哈希值>|s=http://any.com/文件名称|/

   eD2k根哈希值链接    ed2k://|file|<文件名称>|<文件大小>|<文件哈希值>|h=<根哈希值>|/

   直接服务器链接      ed2k://|server|1.1.1.1|1986|/ 

*/

CString strURI(uri);

int iPos = 0;

CString strTok = GetNextString(strURI, _T("|"), iPos);//截取字符串,第一次截取到"|"为止

if (strTok == _T("ed2k://"))//判断strURL的开头是否是ed2k://

{

strTok = GetNextString(strURI, _T("|"), iPos);//此时iPos的值就是第一次次查找"|"的索引+1

if (strTok == _T("file"))//判断第二段字符串是否是file

{

CString strName = GetNextString(strURI, _T("|"), iPos);//此时iPos的值就是第二次查找"|"的索引+1

if (!strName.IsEmpty())//判断表示文件名称的字符串是否为空

{

CString strSize = GetNextString(strURI, _T("|"), iPos);

if (!strSize.IsEmpty())//判断表示文件大小的字符串是否为空

{

CString strHash = GetNextString(strURI, _T("|"), iPos);

if (!strHash.IsEmpty())//判断表示文件哈希值的字符串是否为空

{

//文件哈希值后面的字符串表示各种链接

CStringArray astrEd2kParams;

//声明一个CString类型的数组,CStringArray类用于表示CString的数组

bool bEmuleExt = false;

CString strEmuleExt;

CString strLastTok;

strTok = GetNextString(strURI, _T("|"), iPos);

//从文件哈希值后面的"|",开始截取字符串

while (!strTok.IsEmpty())

{

strLastTok = strTok;

if (strTok == _T("/"))

{

if (bEmuleExt)

break;

bEmuleExt = true;

}

else

{

if (bEmuleExt)

{

if (!strEmuleExt.IsEmpty())

strEmuleExt += _T('|');

strEmuleExt += strTok;

}

else

astrEd2kParams.Add(strTok);

}

strTok = GetNextString(strURI, _T("|"), iPos);

}

if (strLastTok == _T("/"))

return new CED2KFileLink(strName, strSize, strHash, astrEd2kParams, strEmuleExt.IsEmpty() ? (LPCTSTR)NULL : (LPCTSTR)strEmuleExt);

//返回ed2k链接

}

}

}

}

else if (strTok == _T("serverlist"))//判断第二段字符串是否是serverlist

{

CString strURL = GetNextString(strURI, _T("|"), iPos);

if (!strURL.IsEmpty() && GetNextString(strURI, _T("|"), iPos) == _T("/"))

return new CED2KServerListLink(strURL);

}

else if (strTok == _T("server"))//判断第二段字符串是否是server

{

CString strServer = GetNextString(strURI, _T("|"), iPos);

if (!strServer.IsEmpty())

{

CString strPort = GetNextString(strURI, _T("|"), iPos);

if (!strPort.IsEmpty() && GetNextString(strURI, _T("|"), iPos) == _T("/"))

return new CED2KServerLink(strServer, strPort);//产生CED2KServerLink类对象

}

}

}

throw GetResString(IDS_ERR_NOSLLINK);

}

 

 

 

下面对对eMule中的CED2KLink类及其派生类进行简单模拟

#include "iostream"

using namespace std;

class Base

{

public:

static Base* function();

    virtual class Derived1* print1()=0;

};

class Derived1:public Base

{

public:

 Derived1(){cout<<"构造Derived1"<<endl;}

virtual  Derived1* print1();

};

Derived1* Derived1::print1()

{

cout<<"print1"<<endl;

return 0;

}

Base* Base::function()

{

cout<<"function"<<endl;

Base* p=new Derived1();

p->print1();

return 0;

}

int main()

{

Base::function();

return 0;

}

代码已在VC++2005下调试通过

语法说明:在基类的静态函数中产生派生类对象

也就在CED2KLink类的CreateLinkFromUrl函数中可以产生它的三个派生类的对象

参考 

eMule 0.47 源码

http://www.emule-project.net

Emule Document

你可能感兴趣的:(function,server,服务器,File,null,iostream)