Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4094997
  • 博文数量: 1696
  • 博客积分: 10870
  • 博客等级: 上将
  • 技术积分: 18357
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-30 15:16
文章分类
文章存档

2017年(1)

2016年(1)

2015年(1)

2013年(1)

2012年(43)

2011年(17)

2010年(828)

2009年(568)

2008年(185)

2007年(51)

分类: 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+pWnd->m_nWindowDataSize))
{
 ...
}

这里,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分发来的消息。

阅读(786) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~