1. 关于connection的定时器
#define TIME_CONF_CONNECT_TIME (1000 * 30)
改成
#define TIME_CONF_CONNECT_TIME (1000 * 5)
试试效果,看5秒的效果是什么。
注:结果没有什么感觉,恢复原值。
2. CRtReactorBase::ProcessHandleEvent(...)
RtResult CRtReactorBase::
ProcessHandleEvent(RT_HANDLE aFd, IRtEventHandler::MASK aMask,
RtResult aReason, BOOL aIsNotify, BOOL aDropConnect)
{
...
else {
if (maskActual & IRtEventHandler::ACCEPT_MASK
|| maskActual & IRtEventHandler::READ_MASK)
{
nOnCall = eleFind.m_pEh->OnInput(aFd);
}
if ((nOnCall == 0 || nOnCall == -2) &&
(maskActual & IRtEventHandler::CONNECT_MASK
|| maskActual & IRtEventHandler::WRITE_MASK))
{
nOnCall = eleFind.m_pEh->OnOutput(aFd);
}
}
...
}
注:此函数的基本功能就是根据event的类型,调用event handler的OnInput或OnOutput函数,以进行输入或输出操作。
3. Client启动后的thread 总结
启动后主要有几个线程:
* 用户UI线程(主线程)
ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<114229248,262400> >::WindowProc(HWND__ * 0x020a89b8, unsigned int 1, unsigned int 0, long 1269856) line 2110 + 37 bytes
USER32! 77d18734()
USER32! 77d2bdf1()
USER32! 77d28ea0()
USER32! 77d2ce7c()
NTDLL! 7c92e473()
USER32! 77d2e442()
USER32! 77d2e4dc()
WTL::CFrameWindowImplBase<ATL::CWindow,ATL::CWinTraits<114229248,262400> >::Create(HWND__ * 0x00000000, ATL::_U_RECT {...}, const char * 0x001366e0, unsigned long 114229248, unsigned long 262400, ATL::_U_MENUorID {...}, unsigned short 49962, void * 0x00000000) line 456 + 91 bytes
WTL::CFrameWindowImpl<CMainFrame,ATL::CWindow,ATL::CWinTraits<114229248,262400> >::Create(HWND__ * 0x00000000, ATL::_U_RECT {...}, const char * 0x001366e0, unsigned long 114229248, unsigned long 262400, HMENU__ * 0x457a0871, void * 0x00000000) line 1196
WTL::CFrameWindowImpl<CMainFrame,ATL::CWindow,ATL::CWinTraits<114229248,262400> >::CreateEx(HWND__ * 0x00000000, ATL::_U_RECT {...}, unsigned long 0, unsigned long 0, void * 0x00000000) line 1221 + 42 bytes
Run(char * 0x00151f28, int 1) line 195 + 35 bytes
LaunchConf(HINSTANCE__ * 0x00400000, char * 0x00151f28, int 1) line 318 + 13 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00151f28, int 1) line 85 + 20 bytes
WinMainCRTStartup() line 330 + 54 bytes
KERNEL32! 7c817077()
* 网络线程
CRtReactorBase::ProcessHandleEvent(void * 0xffffffff, long 256, int 0, int 1, int 0) line 324 + 18 bytes
CRtReactorWin32Message::Win32SocketWndProc(HWND__ * 0x00130aa2, unsigned int 1058, unsigned int 4294967295, long 256) line 115
USER32! 77d18734()
USER32! 77d18816()
USER32! 77d189cd()
USER32! 77d196c7()
CRtReactorWin32Message::RunEventLoop() line 262 + 15 bytes
CRtThreadReactor::OnThreadRun() line 67 + 19 bytes
CRtThread::ThreadProc(void * 0x020a7ef0) line 151 + 13 bytes
_threadstartex(void * 0x020a7fa0) line 227 + 13 bytes
KERNEL32! 7c80b729()
* 一个同步用的线程(Q:具体功能是什么啊)
NTDLL! 7c92e514()
KERNEL32! 7c802542()
CRtConditionVariableThread::Wait(CRtTimeValue * 0x00000000) line 190 + 26 bytes
CRtEventQueueUsingConditionVariable::PopOrWaitPendingEvents(std::list<IRtEvent *,std::allocator<IRtEvent *> > & {...}, CRtTimeValue * 0x00000000, unsigned long 4294967295) line 159 + 15 bytes
CRtThreadTaskWithEventQueueOnly::OnThreadRun() line 32 + 22 bytes
CRtThread::ThreadProc(void * 0x020ac8b8) line 151 + 13 bytes
_threadstartex(void * 0x020ac9d8) line 227 + 13 bytes
KERNEL32! 7c80b729()
4. 关于WSAsyncSelect()的总结
* STACK TRACE
CRtReactorWin32AsyncSelect::DoAsyncSelect_i(void * 0x00000664, long 63) line 366
CRtReactorWin32AsyncSelect::OnHandleRegister(void * 0x00000664, long 2, IRtEventHandler * 0x020ab300) line 344
CRtReactorBase::RegisterHandler(IRtEventHandler * 0x020ab300, long 2) line 219 + 31 bytes
CRtConnectorTcpT<CRtConnectorWrapper,CRtTransportTcp,CRtSocketStream>::Connect_i(CRtTransportTcp * 0x020ab568, const CRtInetAddr & {...}) line 202 + 25 bytes
CRtConnectorTcpT<CRtConnectorWrapper,CRtTransportTcp,CRtSocketStream>::Connect(const CRtInetAddr & {...}, CRtInetAddr * 0x00000000) line 82 + 22 bytes
CRtConnectorWrapper::AsycConnect(IRtAcceptorConnectorSink * 0x020ab428, const CRtInetAddr & {...}, CRtTimeValue * 0x020ad41c, CRtInetAddr * 0x00000000) line 109 + 26 bytes
CConnConnectorT<CRtConnRlbTcpClient>::AsycConnect(IRtAcceptorConnectorSink * 0x020ad074, const CRtInetAddr & {...}, CRtTimeValue * 0x020ad41c, CRtInetAddr * 0x00000000) line 357 + 84 bytes
CEventAsycConnect::OnEventFire() line 187 + 74 bytes
CRtEventQueueBase::ProcessOneEvent(IRtEvent * 0x020ad3f0) 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__ * 0x000a09a8, unsigned int 1058, unsigned int 4294967295, long 256) line 115
USER32! 77d18734()
USER32! 77d18816()
USER32! 77d189cd()
USER32! 77d196c7()
CRtReactorWin32Message::RunEventLoop() line 262 + 15 bytes
CRtThreadReactor::OnThreadRun() line 67 + 19 bytes
CRtThread::ThreadProc(void * 0x020a7ef0) line 151 + 13 bytes
_threadstartex(void * 0x020a7fa0) line 227 + 13 bytes
KERNEL32! 7c80b
* CODE
RtResult CRtReactorWin32AsyncSelect::
DoAsyncSelect_i(RT_HANDLE aFd, IRtEventHandler::MASK aMask)
{
long lEvent = 0;
if (aMask & IRtEventHandler::CONNECT_MASK)
lEvent |= FD_CONNECT;
if (aMask & IRtEventHandler::ACCEPT_MASK)
lEvent |= FD_ACCEPT;
if (aMask & IRtEventHandler::READ_MASK)
lEvent |= FD_READ;
if (aMask & IRtEventHandler::WRITE_MASK)
lEvent |= FD_WRITE;
if (lEvent != 0)
lEvent |= FD_CLOSE;
else
return RT_OK;
}
注:在网络线程里完成了对WSAAsyncSelect的设置,从而当网络线程中发生相应的网络事件(WM_WIN32_SOCKET_SELECT自定义)的时候,消息处理函数CRtReactorWin32Message::Win32SocketWndProc对其进行相应处理。
static LRESULT CALLBACK Win32SocketWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
5. socket的实例化及WSAAsyncSelect
* STACK TRACE:
CRtReactorWin32AsyncSelect::DoAsyncSelect_i(void * 0x00000664, long 63) line 366
CRtReactorWin32AsyncSelect::OnHandleRegister(void * 0x00000664, long 2, IRtEventHandler * 0x020ab300) line 344
CRtReactorBase::RegisterHandler(IRtEventHandler * 0x020ab300, long 2) line 219 + 31 bytes
CRtConnectorTcpT<CRtConnectorWrapper,CRtTransportTcp,CRtSocketStream>::Connect_i(CRtTransportTcp * 0x020ab568, const CRtInetAddr & {...}) line 202 + 25 bytes
CRtConnectorTcpT<CRtConnectorWrapper,CRtTransportTcp,CRtSocketStream>::Connect(const CRtInetAddr & {...}, CRtInetAddr * 0x00000000) line 82 + 22 bytes
CRtConnectorWrapper::AsycConnect(IRtAcceptorConnectorSink * 0x020ab428, const CRtInetAddr & {...}, CRtTimeValue * 0x020ad41c, CRtInetAddr * 0x00000000) line 109 + 26 bytes
* CODE: CRtConnectorTcpT::Connect()
// interface IRtConnectorInternal
virtual int Connect(const CRtInetAddr &aAddr, CRtInetAddr *aAddrLocal = NULL)
{
int nRet = 0;
const CRtInetAddr *pAddrConnect = &aAddr;
if (aAddrLocal)
m_addrLocal = *aAddrLocal;
......
RT_ASSERTE_RETURN(!m_pTransport, -1);
m_pTransport = new UpTrptType(m_pReactor); // 此处生成了UpTrptType的实例,其实是CRtTransportTcp的实例。
if (!m_pTransport)
return -1;
nRet = Connect_i(m_pTransport, *pAddrConnect);
if (nRet == 0) {
// it rarely happens. we have to OnConnectIndication(RT_OK) to upper layer.
RT_WARNING_TRACE_THIS("CRtConnectorTcpT::Connect, connect return 0.");
nRet = m_pReactor->NotifyHandler(this, IRtEventHandler::WRITE_MASK);
}
else if (nRet == 1)
nRet = 0;
return nRet;
}
* CODE: CRtConnectorTcpT::Connect_I()
int Connect_i(UpTrptType *aTrpt, const CRtInetAddr &aAddr)
{
int nRet;
UpSockType &sockPeer = aTrpt->GetPeer();
RT_ASSERTE(sockPeer.GetHandle() == RT_INVALID_HANDLE);
if (m_addrLocal == CRtInetAddr::s_rtInetAddrNull)
nRet = sockPeer.Open(FALSE);
else
nRet = sockPeer.Open(FALSE, m_addrLocal);
......
if (sockPeer.Enable(RT_IPC_SAP::NON_BLOCK) == -1) {
RT_ERROR_TRACE_THIS("CRtConnectorTcpT::Connect_i, Enable(NON_BLOCK) failed! err=" << RtGetSystemErrorInfo(errno));
return -1;
}
......
/// we regiester CONNECT_MASK prior to connect() to avoid lossing OnConnect()
RtResult rv = m_pReactor->RegisterHandler(this, IRtEventHandler::CONNECT_MASK);
if (RT_FAILED(rv))
return -1;
nRet = ::connect((RT_SOCKET)sockPeer.GetHandle(),
reinterpret_cast<const struct sockaddr *>(aAddr.GetPtr()),
aAddr.GetSize()); // 此处,终于修成成果,连接建立,tcpview.exe能看到了。
......
}
总结一下:
# 网络线程启动
# 创建到远端(server)的连接Socket
# WSAAsyncSelect绑定到CRtReactorWin32Message::Win32SocketWndProc
# 连接server(::Connect())
5. Client启动过程总结,关注以下几点:
* 线程
* 网络端口
* 与服务器端的各种交互
* 网络线程与主线程之间的交互方式