eMule源码主要调用流程分析

轉載自: http://hustlg.bokee.com/6512080.html

 

从事P2P下载开发的原因,仔细分析了eMule下载的协议和实现的技术细节,下面是对eMule源代码下载流程的简要分析:

主体结构:(按照下面的调用顺序启动主要流程)
      1.Emule对话框类CEmuleDlg::OnInitDlg ::SetTimer(NULL, NULL, 300, StartupTimer) 设置启动定时器;

      2.  定时器函数void CALLBACK CemuleDlg::StartupTimer(。。)完成各对象初始化初始化服务器列表

       3. theApp.serverlist->Init();从文件中读取 struct ServerMet_Struct {  uint32 ip;  uint16 port; uint32

tagcount;}+tag ( 标签)和从文本文件读取静态server列表;

      4. 下载队列初始化 theApp.downloadqueue->Init();

       5. 启动客户端监听 theApp.listensocket->StartListening()CClientUDPSocket对象创建套接字theApp.clientudp-

>Create()

        6.检测启动是否自动连接服务器if (thePrefs.DoAutoConnect())连接emule服务器    theApp.emuledlg-

>OnBnClickedButton2();

          7. 调用connectserver对象的trytoconnectanyserver()连接全局服务器。

下载文件的流程:

 详细见类CServerConnect的分析从下载搜索结果中选择下载一个文件程序调用流程:

1。CSearchResultsWnd::OnBnClickedDownloadSelected()-->CSearchResultsWnd::DownloadSelected(bool bPaused --

>theApp.downloadqueue->AddSearchToDownload(&tempFile, bPaused, m_cattabs.GetCurSel());--〉

CDownloadQueue::AddDownload()加入下载队列尾部。

2。 开始下载在由static VOID CALLBACK CUploadQueue::UploadTime  定时器函数处{..theApp.downloadqueue->Process

();..}CUploadQueue::CUploadQueue()  //构造函数设的  的 置定时器100毫秒  { VERIFY( (h_timer = SetTimer

(0,0,100,UploadTimer)) != NULL );。….} 下载在CDownloadQueue::Process()处理--> CPartFile::Process()--

>CUpDownClient::AskForDownload{ SetDownloadState(DS_CONNECTING); return TryToConnect();…}       

3。进入 CUpDownClient ::TryToConnect(){  建立客户端请求socket对象并创建socket  CClientReqSocket * socket =

static_cast(pClassSocket->CreateObject());  socket->SetClient(this);  if (!socket->Create())如果该客户端是lowid

发送callback请求否则调用CUpDownClient::Connect()和该源客户端发起tcp连接请求由socket->Connect完成然后发送握手请求

op_hello;

4。接下来CClientReqSocket 类ProcessPacket中进行等待处理 OP_HELLOANSWER在 case OP_HELLOANSWER:    {       client

->ProcessHelloAnswer(packet,size);       if (client)     {      client->ConnectionEstablished() }--

>CUpDownClient::ConnectionEstablished() {switch(GetDownloadState()) {  case DS_CONNECTING: CUpDownClient::

SendFileRequest()…负责发出文件下载相关请求的操作 OP_MULTIPACKET 将多个消息打包作为一个新消息发送支持

WritePartStatus 文件状态的表示 每个部分用一个二进制位表示,完成为1否则为0                }

  5。 接下来发出OP_STARTUPLOADREQ请求,CUpDownClient::SendStartupLoadReq()请求开始下载文件(如果有其他客户端在下

载同一个文件,那么下载客户端将被放入上传队列中连接断开。)        (当下载客户端到达上传客户端上传队列顶部时如果

连接已断开,上传客户端连接下载客户端,如果连接已断开连接建立后发送

OP_ACCEPTUPLOADREQCUploadQueue::AddUpNextClient(LPCTSTR pszReason, CUpDownClient* directadd)第一个参数说明了每次

调用该函数增加客户端上传的原因(即从上传等待队列放入正在上传的队列。// tell the client that we are now ready to

upload if (!newclient->socket || !newclient->socket->IsConnected()) {     if (!newclient->TryToConnect(true))   

} else {   Packet* packet = new Packet(OP_ACCEPTUPLOADREQ,0);}void CUploadQueue::Process()  每100毫秒调用一次 if

(ForceNewClient()){AddUpNextClient(_T("Not enough open upload slots for current ul speed"));}cur_client-

>SendBlockData();

  6. 发送peer请求的数据块CUpDownClient::ConnectionEstablished()                case US_CONNECTING:  case

US_WAITCALLBACK:   if (theApp.uploadqueue->IsDownloading(this))   {    SetUploadState(US_UPLOADING);        

Packet* packet = new Packet(OP_ACCEPTUPLOADREQ,0);         socket->SendPacket(packet,true);   })文件正式开始下

载是接收到OP_ACCEPTUPLOADREQ消息开始,case OP_ACCEPTUPLOADREQ:client->ProcessAcceptUpload

();CUpDownClient::ProcessAcceptUpload()-->CUpDownClient::StartDownload()-->CUpDownClient::SendBlockRequests()

网络层相关类:

class CEMSocketvirtual bool PacketReceived(Packet* packet) = 0; protected处理接收到的网络数据包,被定义为纯虚函

数,各网络相关类由lass CEMSocket派生,各自对收到的包的处理不同。该函数在OnReceive中被调用OnReceive同样为虚函数

class CListenSocket 负责每个客户端监听一个tcp端口,每接受一个其他客户端tcp连接就创建一个CClientReqSocket对象,来

处理对应的客户端发送的相关消息。CUpDownClient 试图连接其他客户端的时候也会创建一个CClientReqSocket的对象以连接到

其他peerCEMSocket::OnSend(int nErrorCode){;if(m_currentPacket_is_controlpacket) {        // queue up for

control packet        theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this, HasSent());    }

发送的数据报分两种受控和标准, 受控数据报优先级较高Sendpacket() 将数据报推向受控队列,并且相关soket对象指针加入流

量控制对象中,最终由流量控制类通过指针调用socket对象的send函数发送网络数据,        if (controlpacket) {        

controlpacket_queue.AddTail(packet);            // queue up for controlpacket           

theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this, HasSent());

    标准数据报被推往标准队列中CserverConnect类主要功能,维护和文件服务器的联接。

    流量控制相关类UploadBandwidthThrottler uploadBandwidthThrottler 全局有一个该对象,发送的数据报

UploadBandwidthThrottler类对象在 CemuleApp::InitInstance()种建立uploadBandwidthThrottler = new

UploadBandwidthThrottler();在构造函数中启动数据报发送控制的线程AfxBeginThread(RunProc, (LPVOIDthis);

     UploadBandwidthThrottler::RunInternal(){socket->SendControlData( 发送送控数据包socket-

>SendFileAndControlData(发送标准数据包CClientReqSocket   负责建立和其他客户端的tcp连接 ,监听其他客户端请求消息

和处理 协议消息,该类支持动态创建CUpDownClient 对应没个上传下载的客户端启动文件hash线程start aichsyncthread

AfxBeginThread(RUNTIME_CLASS(CAICHSyncThread), THREAD_PRIORITY_BELOW_NORMAL,0);

  关于eMule的源码分析和协议分析细节可以参考我翻译的文档和撰写的源码分析报告诉。文档下载地址:http://hi.csdn.net/ganghust/profile,我的个人空间的资源部分。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
#define OP_EDONKEYHEADER 0xE3 #define OP_KADEMLIAHEADER 0xE4 这是他的协议码,他大部分的通信包第一个字节都是OP_EDONKEYHEADER 0xE3, 这是他的客户端之间的协议 #define OP_HELLO 0x01 // 0x10<HASH 16><ID 4><PORT 2><1 Tag_set> #define OP_SENDINGPART 0x46 // <HASH 16><von 4><bis 4><Daten len:(von-bis)> #define OP_REQUESTPARTS 0x47 // <HASH 16><von[3] 4*3><bis[3] 4*3> #define OP_FILEREQANSNOFIL 0x48 // <HASH 16> #define OP_END_OF_DOWNLOAD 0x49 // <HASH 16> #define OP_ASKSHAREDFILES 0x4A // (null) #define OP_ASKSHAREDFILESANSWER 0x4B // <count 4>(<HASH 16><ID 4><PORT 2><1 Tag_set>)[count] #define OP_HELLOANSWER 0x4C // <HASH 16><ID 4><PORT 2><1 Tag_set><SERVER_IP 4><SERVER_PORT 2> #define OP_CHANGE_CLIENT_ID 0x4D // <ID_old 4><ID_new 4> #define OP_MESSAGE 0x4E // <len 2><Message len> #define OP_SETREQFILEID 0x4F // <HASH 16> #define OP_FILESTATUS 0x50 // <HASH 16><count 2><status(bit array) len:((count+7)/8)> #define OP_HASHSETREQUEST 0x51 // <HASH 16> #define OP_HASHSETANSWER 0x52 // <count 2><HASH[count] 16*count> #define OP_STARTUPLOADREQ 0x54 // <HASH 16> #define OP_ACCEPTUPLOADREQ 0x55 // (null) #define OP_CANCELTRANSFER 0x56 // (null) #define OP_OUTOFPARTREQS 0x57 // (null) #define OP_REQUESTFILENAME 0x58 // <HASH 16> (more correctly file_name_request) #define OP_REQFILENAMEANSWER 0x59 // <HASH 16><len 4><NAME len> #define OP_CHANGE_SLOT 0x5B // <HASH 16> #define OP_QUEUERANK 0x5C // <wert 4> (slot index of the request) #define OP_ASKSHAREDDIRS 0x5D // (null) #define OP_ASKSHAREDFILESDIR 0x5E // <len 2><Directory len> #define OP_ASKSHAREDDIRSANS 0x5F // <count 4>(<len 2><Directory len>)[count] #define OP_ASKSHAREDFILESDIRANS 0x60 // <len 2><Directory len><count 4>(<HASH 16><ID 4><PORT 2><1 Tag_set>)[count] #define OP_ASKSHAREDDENIEDANS 0x61 // (null) 这是他的客户端到服务器的通信协议

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值