1. Chat Module接收信息,并演示到UI上面的全过程:
STACK TRACE:
CChatMainDlg::ReceiveMessage(unsigned long 19923456, WTL::CString & {...}, WTL::CString & {...}, int 1, _charformatw * 0x00119fa8) line 589
CChatMainDlg::ReceiveData(const CInfoSID & {...}, unsigned long 54, unsigned char * const 0x01f65db8) line 545
CChatSession::OnReceiveData(const CInfoSID & {...}, const CInfoSID & {...}, DATA_Priority DATA_PRIORITY_HIGH, unsigned long 2, unsigned long 54, unsigned char * const 0x01f65db8) line 634
CConfSession::OnReceiveData(const CInfoSID & {...}, const CInfoSID & {...}, DATA_Priority DATA_PRIORITY_HIGH, unsigned long 2, unsigned long 54, unsigned char * const 0x01f65d31) line 514 + 49 bytes
CConference::HandleSessApplicationData(CInfoSvrSessApplicationData * 0x01f635d0) line 1972 + 96 bytes
CConference::OnReceiveData(CRtMessageBlock & {...}) line 1342
CConfConnection::OnReceiveData(CRtMessageBlock & {...}, IConnection * 0x01efdf5c) line 170
CRtIMConnection::OnReceive(CRtMessageBlock & {...}, IRtTransport * 0x01efbe90, CRtTransportParameter * 0x00000000) line 890 + 50 bytes
CRtEventOnReceive::OnEventFire() line 375 + 50 bytes
CRtEventQueueBase::ProcessOneEvent(IRtEvent * 0x01f121d0) line 229 + 12 bytes
CRtEventQueueBase::ProcessEvents(const std::list<IRtEvent *,std::allocator<IRtEvent *> > & {...}) line 217
CRtReactorBase::ProcessHandleEvent(void * 0xffffffff, long 256, int 0, int 1, int 0) line 324 + 18 bytes
CRtReactorWin32Message::Win32SocketWndProc(HWND__ * 0x00050804, unsigned int 1058, unsigned int 4294967295, long 256) line 115
USER32! 77d18734()
USER32! 77d18816()
USER32! 77d189cd()
USER32! 77d196c7()
WTL::CMessageLoop::Run() line 468 + 15 bytes
Run(char * 0x00141f37, int 1) line 207 + 11 bytes
LaunchConf(HINSTANCE__ * 0x00400000, char * 0x00141f37, int 1) line 318 + 13 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00141f37, int 1) line 85 + 20 bytes
WinMainCRTStartup() line 330 + 54 bytes
KERNEL32! 7c817077()
Q:Win32SocketWndProc()被调用是谁决定的?所有这些对象的实例化过程?
A:在CRtReactorWin32Message::Open()中将Win32SocketWndProc注册了。 2011/12/04
Q:网络程序用的message loop与CMainFrame使用的消息循环是同一个吗?
A:不同,因为在不同的线程中,一个是main (UI) thread,一个是network thread。 2011/12/04
2. 杂项
* How to understand Win32SocketWndProc ?
Reactor模式相关文章:http://woshao.com/article/4ab7b9e8589911e099b5000c2959fd2a/
Windows Socket的WSAAsyncSelect模型
3. CRtReactorWin32Message
* 初始化
STACK TRACE
CRtReactorWin32Message::Open() line 163
CRtThreadReactor::Create(int 0, CRtThreadManager::TFlag TF_JOINABLE) line 40 + 19 bytes
CRtThreadManager::CreateReactorThread(int 0, IRtReactor * 0x01ef81d8, CRtThread * & 0x00000000) line 368 + 41 bytes
CRtThreadManager::InitMainThread(int 0, char * * 0x00000000) line 191 + 24 bytes
CRtThreadManager::Instance() line 132 + 15 bytes
RtCoInitialize() line 179 + 5 bytes
ILDebugStart(unsigned short 33201, void * 0x00000001) line 1482
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00141f37, int 1) line 83 + 8 bytes
WinMainCRTStartup() line 330 + 54 bytes
KERNEL32! 7c817077()
注:在WinMain()中启动Debug Service(为什么是Debug?名字很怪)时,CRtReactorWin32Message::Open()被呼叫,并在此函数中完成窗口WinSocket 32窗口响应函数的注册。
* CRtReactorWin32Message::Open
RtResult CRtReactorWin32Message::Open()
{
RtResult rv = RT_ERROR_UNEXPECTED;
g_pReactorWin3Instance = ::GetModuleHandle(NULL);
RT_ASSERTE_RETURN(!m_hwndNotify, RT_ERROR_ALREADY_INITIALIZED);
#ifdef RT_ENABLE_CALENDAR_TIMER
m_CalendarTimer.m_Est.Reset2CurrentThreadId();
#endif // RT_ENABLE_CALENDAR_TIMER
rv = CRtReactorBase::Open();
if (RT_FAILED(rv))
goto fail;
if (g_atomRegisterClass == 0) {
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = Win32SocketWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(void*);
wc.hInstance = g_pReactorWin3Instance;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = WIN32_SOCKET_CLASS_NAME;
if ((g_atomRegisterClass = ::RegisterClass(&wc)) == 0) {
RT_ERROR_TRACE_THIS("CRtReactorWin32Message::Open, RegisterClass() failed!"
" err=" << ::GetLastError());
rv = RT_ERROR_FAILURE;
goto fail;
}
......
m_hwndNotify = ::CreateWindow(WIN32_SOCKET_CLASS_NAME, NULL, WS_OVERLAPPED, 0,
0, 0, 0, NULL, NULL, g_pReactorWin3Instance, 0);
if (!m_hwndNotify) {
RT_ERROR_TRACE_THIS("CRtReactorWin32Message::Open, CreateWindow() failed!"
" err=" << ::GetLastError());
rv = RT_ERROR_FAILURE;
goto fail;
}
......
::SetWindowLong(m_hwndNotify, 0, (LONG)this)
^ 将当前对象(也就是CRtReactorWin32Message)指针存在Windows数据区中,
^ 供Windows Handler函数在处理的时候使用reactor->ProcessHandleEvent来处理。 2011/12/04
......
return RT_OK;
.......
}
Q: created an invisible window ?
A:YES !
注:SetWindowLong(...)将当前Reactor对象存在m_hwndNotify窗口的index为0的特殊存储区域中,在后来的消息响应函数中可以据此找到此Reactor的实例。
例入网络上有信息传过来的时候,如下代码:
Win32SocketWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_WIN32_SOCKET_SELECT:
...
CRtReactorWin32Message *pReactor= (CRtReactorWin32Message *)::GetWindowLong(hwnd, 0);
pReactor->XXX();
......
}
Q: why cannot find Win32SocketWndProc function in the computers at home ?
4. WSAAsyncSelect
::WSAAsyncSelect(sListen, hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE);