分类: C/C++
2010-03-21 22:04:19
CAsyncSocketExHelperWindow的消息callback方法是WindowsProc,这是在创建窗口时指定的:
wndclass.lpfnWndProc=WindowProc;
WindowProc处理了5种类型的message
(1) >= WM_SOCKETEX_NOTIFY
(2)
WM_USER
CAsyncSocketExLayer用到的消息,如果不使用layer,不会有这个消息
(3) WM_USER+1
(4)
WM_USER + 2
(5) WM_TIMER
我们先分析最重要的第一种消息,message>= WM_SOCKETEX_NOTIFY,这个消息是socket上有指定的lEvent发生时,发送来的。使用的windows api是WSAAsyncSelect()。
下面条件指定了,如果message大于WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize,就不处理
这条消息。
if
(message
{
...
}
这里,WM_SOCKETEX_NOTIFY是一个基线,即所有socket消息中message都是从WM_SOCKETEX_NOTIFY开始
的,CAsyncSocketExHelperWindow的成员变量m_pAsyncSocketExWindowData维护了一个需要分发消息的
socket数组,根据FileZilla规则,socket在这个数组中的位置决定了消息的message值。即数组中第0个socket的所有消息
message都是WM_SOCKETEX_NOTIFY +
0,数组中第1个socket的所有消息message都是WM_SOCKETEX_NOTIFY +
1,依次类推,因此如果message大于WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize,实际就意味着
这不是一个合法的消息。这里,我们可以看一下create时,调用WSAAsyncSelect时的代码:
if (
!WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(),
m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, lEvent) )
return
TRUE;
参数中,
m_SocketData.hSocket指的是CAsyncSocketEx通过socket()创建的windows
socket,
GetHelperWindowHandle()指的就是CAsyncSocketExHelperWindow,
m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY
指的就是发送消息的message值,是基数加上在数组中的位置:nSocketIndex
lEvent指的是socket有何种event时,
发送消息
往下看消息的处理过程:
CAsyncSocketEx
*pSocket=pWnd->m_pAsyncSocketExWindowData[message-WM_SOCKETEX_NOTIFY].m_pSocket;
SOCKET
hSocket=wParam;
...
int nEvent=lParam&0xFFFF;
int
nErrorCode=lParam>>16;
这里通过message-WM_SOCKETEX_NOTIFY找到这条消息所属的
CAsyncSocketEx,这里wParam指定了socket,这其实和pSocket是一回事,两者都对应一个socket,或者说是
CAsyncSocketEx。lParam指定发生了何种event。
一般情况下if (!pSocket->m_pFirstLayer)都会成立,即没有m_pFirstLayer,因此我们看if
(!pSocket->m_pFirstLayer)对应的代码,
switch (nEvent)
{
...
}
显
然是对nEvent进行分析,中间代码有很多
#ifndef NOSOCKETSTATES
#endif
//NOSOCKETSTATES
这是用来设置socket状态的,暂时可以忽略,即可以删掉这个中间的代码,整个程序会清爽很多:
switch (nEvent)
{
case FD_READ:
if (pSocket->m_lEvent & FD_READ)
{
DWORD
nBytes = 0;
if (!nErrorCode)
if
(!pSocket->IOCtl(FIONREAD, &nBytes)) // 看看能读多少个字节
nErrorCode
= WSAGetLastError();
if (nBytes != 0 || nErrorCode != 0)
pSocket->OnReceive(nErrorCode);
}
break;
case
FD_FORCEREAD: //Forceread does not check if there's data waiting
if
(pSocket->m_lEvent & FD_READ)
{
pSocket->OnReceive(nErrorCode);
}
break;
case
FD_WRITE:
if (pSocket->m_lEvent & FD_WRITE)
{
pSocket->OnSend(nErrorCode);
}
break;
case
FD_CONNECT:
if (pSocket->m_lEvent & FD_CONNECT)
pSocket->OnConnect(nErrorCode);
break;
case
FD_ACCEPT:
if (pSocket->m_lEvent & FD_ACCEPT)
pSocket->OnAccept(nErrorCode);
break;
case
FD_CLOSE:
pSocket->OnClose(nErrorCode);
break;
}
很清楚,nEvent以下几种类型,分别调用了相应CAsyncSocketEx的On方法:
FD_READ
CAsyncSocketEx::OnReceive
FD_FORCEREAD
CAsyncSocketEx::OnReceive
FD_WRITE
CAsyncSocketEx::OnSend
FD_CONNECT
CAsyncSocketEx::OnConnect
FD_ACCEPT
CAsyncSocketEx::OnAccept
FD_CLOSE
CAsyncSocketEx::OnClose
打
开这些On方法看一下,CAsyncSocketEx提供了空的实现,这是合理的,CAsyncSocketEx是基类,它并不清楚应该怎样处理这些消
息,这肯定应该由子类来实现这些On方法。
分析了CAsyncSocketEx类以后,我们大致清楚了整个socket处理的机制,下面就要对一个个具体的继承于
CAsyncSocketEx的类进行分析,看看到底怎样来处理这些从socket分发来的消息。