注册 登录
LUPA开源社区 返回首页

yyq224444的个人空间 http://www.lupaworld.com/?439809 [收藏] [复制] [分享] [RSS]

我的博客

飞鸽程序分析(二)

热度 4已有 2553 次阅读2011-5-25 08:50 |个人分类:网络编程|系统分类:IT技术|

下面先说一下程序从启动到发送第一条广播信息的过程:

首先整个程序从这里开始

int APIENTRY WinMain(HINSTANCE hI, HINSTANCE, LPSTR cmdLine, int nCmdShow)

{

       TMsgApp       app(hI, cmdLine, nCmdShow);

      

       return      app.Run();

}

这个程序创建了一个TMsgApp的对象appTMsgAppTApp的子类,初始化app后,运行appRun函数,这个函数继承自TApp类:

int TApp::Run(void)

{

       MSG              msg;

 

       InitApp();//TApp中定义的函数

       InitWindow();//TMsgApp中定义的函数

 

       while (::GetMessage(&msg, NULL, 0, 0))

       {

              if (PreProcMsg(&msg))

                     continue;

 

              ::TranslateMessage(&msg);

              ::DispatchMessage(&msg);

       }

 

       return      msg.wParam;

}

 

TMsgAppInitWindows()主要作用是注册了一个windowclass类型(TApp::WinProc函数作为窗口消息的处理函数),并且创建了一个TMainWin类的对象hWnd。并调用TMainWin中的Create函数,Create函数将这个窗口类加到TApp中的静态窗口链表中(TApp::AddWin(this))

Run函数剩下的部分主要是一个while循环,主要做的是从消息列表中抓取消息,然后将消息函数发送给TAppWinproc函数处理消息。

TAppWinProc函数:

LRESULT CALLBACK TApp::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

       TWin *win = SearchWnd(hWnd);

       if (win)

              return      win->WinProc(uMsg, wParam, lParam);

 

       if ((win = preWnd) != NULL)

       {

              preWnd = NULL;

              AddWinByWnd(win, hWnd);

              return      win->WinProc(uMsg, wParam, lParam);

       }

 

       return      DefWindowProc(hWnd, uMsg, wParam, lParam);

}

它的主要过程是通过SerchWnd函数在wndArray窗口链表中查找到当前msg消息的产生的窗口的句柄。然后调用窗口的WinProc函数。若此窗口不在wndArray中,那么通过AddWinByWnd()函数将它加到wndArray中,然后再调用窗口的WinProc函数。

 

在程序刚开始的时候TMainWnd的对象Hwnd调用CreateWindowEx创建完窗口后的时候会发送WM_CREATE消息到消息列表,Run函数中的while循环提取这个消息的时候会转交给TApp::WinProc处理,TApp::WinProc函数会将此消息传递给Twin::WinProc函数处理,在Twin::WinProc函数中的会调用,由于虚函数机制,其实调用的是TMainWndWinProc函数,根据消息WM_CREATE,调用TMainWin::EvCreate()函数:

BOOL TMainWin::EvCreate(LPARAM lParam)

{

       hMainWnd = hWnd;

       mainWin = this;

       if (msgMng->GetStatus() != TRUE)

              return      TRUE;

       if (IsNewShell())

       {

              Show(SW_HIDE);

              while (TaskBar(NIM_ADD, hMainIcon, IPMSG_MSGSTR) != TRUE)//设置任务栏

//图标文字信息

                     Sleep(1000);   // for logon script

       }

       else

              Show(SW_MINIMIZE);

       TaskBarCreateMsg= ::RegisterWindowMessage("TaskbarCreated");

       msgMng->AsyncSelectRegist(hWnd);//TCPUDP消息和当前的窗口hWnd联系起来

 

       if (msgMng->GetStatus())

              EntryHost();//传输管理类设置完毕后进入EntryHost函数

 

       PostMessage(WM_SENDDLG_OPEN,0,0);

       return      TRUE;

}

TMainWin::EvCreate()函数的作用就是设置任务栏的图标和文字 ,还有就是将WM_TCPEVENTWM_UDPEVENT消息和当前的窗口联系起来,也就是这两个消息由当前窗口完成处理。紧接着就是进入EntryHost函数。这个函数负责当前主机向全网发送广播。或者更新在线的主机列表。

EntryHost()函数:

void TMainWin::EntryHost(void)

{

       time_t     now_time = Time();

       if (entryStartTime + (time_t)cfg->ListGetMSec / 1000 > now_time)

              return;

       entryStartTime = now_time;

 

       if (cfg->ListGet)//定时发送广播的信息

       {

              if (::SetTimer(hWnd, IPMSG_LISTGET_TIMER, cfg->ListGetMSec, NULL))

                     entryTimerStatus = IPMSG_LISTGET_TIMER;

              BroadcastEntry(IPMSG_BR_ISGETLIST2);

       }

       else

              BroadcastEntry(IPMSG_BR_ENTRY);//首次向全网广播当前主机上线的消息

}

 

此函数的作用在这里主要的作用就是调用BroadcastEntry()向全网发送IPMSG_BR_ISGETLIST2或者IPMSG_BR_ENTRY的消息。

BroadcastEntry()函数的作用是通过调用

BroadcastEntrySub((ULONG)~0, htons(portNo), IPMSG_NOOPERATION);想全网发送一个IPMSG_NOOPERATION的广播,然后睡眠一段时间,再向全网发送一个IPMSG_BR_ENTRR的消息,这个是直接使用MsgMng提供的send函数发送UDP消息。

下面这句话设置了一个固定时间发送一个包含IPMSG_ENTRY_TIMER字段的WM_TIMER的消息。

if (mode == IPMSG_BR_ENTRY && cfg->ExtendEntry)

::SetTimer(hWnd, IPMSG_ENTRY_TIMER, IPMSG_ENTRYMINSEC * 1000, NULL);

BroadcastEntrySub()函数是将地质和端口封装成Hostsub类对象后通过MsgMngsend函数发送UDP消息。

这就是启动后发送广播的整个过程。并且调用setTimer函数定时发送WM_TIMER消息。

 

我们注意到在上面讲到TMainWin::EvCreate函数的时候,最后一句代码:

PostMessage(WM_SENDDLG_OPEN,0,0);

这句代码告诉我们向消息队列发送一个WM_SENDDLG_OPEN的消息。这就使得成寻启动后会触发TSendDlg对话框的显示。同样的WM_SENDDLG_OPEN消息也是会在TApp::Run中处理,也会想WM_CREATE消息一样最终交付到产生这个消息的TMainWin的窗口的WinProc函数中去,由于WM_SENDDLG_OPEN消息是我们自定义的消息所以,我们需要调用TMainWin::EventUser 函数处理这个消息,在EventUser函数中我们可以看到响应这个消息的函数是SendDlgOpen函数,在这个函数中,我们创建了以个对话框窗口sendDlg。并将这个对话框窗口链接到sendList(sendList.AddObj(sendDlg))

 

广播的过程说完了,下面说说接收UDP消息的过程:

 

当程序接收到一个UDP消息的时候会触发WM_UDPEVENT消息,这时TApp::Run函数将此消息传递给TApp::WinProc函数,因为之前设定WM_UDPEVENT消息与TMainWin窗口类绑定,所以调用TMainWin类的WinProc函数,由于WM_UDPEVENT是用户自定义的消息,所以TMainWin::WinProc将调用TMainWin::EventUser函数,EventUser函数中调用TMainWin::UdpEvent函数,而UdpEvent函数则是根据msg中的command命令字段的值选择对应的函数。例如当接收到有IPMSG_BR_ENTRY字段的消息的时候,则会调用MsgBrEntry函数,这个函数会从消息中提取发送者的名字和主机名等信息,然后加入到ansList链表中。

 

 已同步至 yyq224444的微博
 已同步至 yyq224444的微博

刚表态过的朋友 (0 人)

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册
验证问答 换一个 验证码 换一个

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部