MFC 中CAsyncSocket套接字的创建及窗口与消息绑定,消息处理内部实现过程。

以下是MFC   在vc10中实际的代码及我给出的注解,更具说明意义可以看到套接字的创建与窗口绑定过程,以及DoCallBack如何处理收到的消息

1)BOOL CAsyncSocket::Create(UINT nSocketPort, int nSocketType,

    long lEvent, LPCTSTR lpszSocketAddress)

{

    if (Socket(nSocketType, lEvent))

    {

        if (Bind(nSocketPort,lpszSocketAddress))//HY:为套接字绑定地址

            return TRUE;

        int nResult = GetLastError();

        Close();

        WSASetLastError(nResult);

    }

    return FALSE;

}

2)BOOL CAsyncSocket::Socket(int nSocketType, long lEvent,

    int nProtocolType, int nAddressFormat)

{

    ASSERT(m_hSocket == INVALID_SOCKET);

    m_hSocket = socket(nAddressFormat,nSocketType,nProtocolType);

    if (m_hSocket != INVALID_SOCKET)//HY:套接字有效则加入活动套接字,字典(套接字,套接字对象,是否是死套接字(非活动的)。

    {

        CAsyncSocket::AttachHandle(m_hSocket, this, FALSE);

        return AsyncSelect(lEvent);  //HY:注意这句实现了套接字,窗口,消息,事件的绑定

    }

    return FALSE;

}

3void PASCAL CAsyncSocket::AttachHandle(

    SOCKET hSocket, CAsyncSocket* pSocket, BOOL bDead)//HY:bDead 为TRUE时证明是一个非活动的套接字。

{

    _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

    BOOL bEnable = AfxEnableMemoryTracking(FALSE);

    TRY

    {

        if (!bDead)  //HY:如果是一个活动的“活”套接字

        {

            ASSERT(CAsyncSocket::LookupHandle(hSocket, bDead) == NULL);//HY:从MAP(字典结构)中找指定的对象元素

            if (pState->m_pmapSocketHandle->IsEmpty())

            {

                ASSERT(pState->m_pmapDeadSockets->IsEmpty());

                ASSERT(pState->m_hSocketWindow == NULL);

                CSocketWnd* pWnd = new CSocketWnd;    //HY: 构建一个SOCKETWND对象

                pWnd->m_hWnd = NULL;

                if (!pWnd->CreateEx(0, AfxRegisterWndClass(0), 

                    _T("Socket Notification Sink"),

                    WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL)) //HY: SOCKETWND对象

的窗口m_hWnd句柄装载

                {

                    TRACE(traceSocket, 0, "Warning: unable to create socket notify window!\n");

                    delete pWnd;

                    AfxThrowResourceException();

                }

                ASSERT(pWnd->m_hWnd != NULL);

                ASSERT(CWnd::FromHandlePermanent(pWnd->m_hWnd) == pWnd);  //HY: FromHandlePermanent从指定句柄中得到对象实例

                pState->m_hSocketWindow = pWnd->m_hWnd;

            }

            pState->m_pmapSocketHandle->SetAt((void*)hSocket, pSocket);//HY:字典结构添加socket(套接字值)与CAsyncSocket实例的对应关系。

        }

        else //HY:如果是一个非活动套接字

        {

            void* pvCount;

            INT_PTR nCount;

            if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, pvCount))

            {

                nCount = (INT_PTR)pvCount;

                nCount++;

            }

            else

                nCount = 1;

            pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);

        }

    }

    CATCH_ALL (e)

    {

        AfxEnableMemoryTracking(bEnable);

        THROW_LAST();

    }

    END_CATCH_ALL

    AfxEnableMemoryTracking(bEnable);

}

//HY:ATTACH先完成对象中套接字的赋值然后调用了AttachHandle和AsyncSelect

4)BOOL CAsyncSocket::Attach(SOCKET hSocket, long lEvent)

{

    ASSERT(hSocket != INVALID_SOCKET);

    if (hSocket == INVALID_SOCKET)

    {

        WSASetLastError (WSA_INVALID_HANDLE);

        return FALSE;

    }

    m_hSocket = hSocket;

    CAsyncSocket::AttachHandle(hSocket, this);

    return AsyncSelect(lEvent);

}

5)BOOL CAsyncSocket::AsyncSelect(long lEvent)

{

    ASSERT(m_hSocket != INVALID_SOCKET);

    _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

    ASSERT(pState->m_hSocketWindow != NULL);

    return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow,

        WM_SOCKET_NOTIFY, lEvent) != SOCKET_ERROR;   //HY:完成套接字、窗口、消息类型、事件绑定。

}

6)void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)

{

    if (wParam == 0 && lParam == 0)

        return;

    // Has the socket be closed - lookup in dead handle list

    CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE);

    // If yes ignore message

    if (pSocket != NULL)

        return;

    pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE); //HY:在存活字典中查找

    if (pSocket == NULL)

    {

        // Must be in the middle of an Accept call

        pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);

        ASSERT(pSocket != NULL);

        if(pSocket == NULL)

            return;

           

        pSocket->m_hSocket = (SOCKET)wParam;  //HY:对CAsyncSocket对象的m_hSocket赋当前套接字值

        CAsyncSocket::DetachHandle(INVALID_SOCKET, FALSE);  //HY:失效套接字字典结构,中去掉当前对象

        CAsyncSocket::AttachHandle(pSocket->m_hSocket, pSocket, FALSE);

    }

    int nErrorCode = WSAGETSELECTERROR(lParam);

    switch (WSAGETSELECTEVENT(lParam))

    {

    case FD_READ:

        {

            fd_set fds;

            int nReady;

            timeval timeout;

            timeout.tv_sec = 0;

            timeout.tv_usec = 0;

            FD_ZERO(&fds);

            FD_SET(pSocket->m_hSocket, &fds);

            nReady = select(0, &fds, NULL, NULL, &timeout);

            if (nReady == SOCKET_ERROR)

                nErrorCode = WSAGetLastError();

            if ((nReady == 1) || (nErrorCode != 0))

                pSocket->OnReceive(nErrorCode);

        }

        break;

    case FD_WRITE:

        pSocket->OnSend(nErrorCode);

        break;

    case FD_OOB:

        pSocket->OnOutOfBandData(nErrorCode);

        break;

    case FD_ACCEPT:

        pSocket->OnAccept(nErrorCode);

        break;

    case FD_CONNECT:

        pSocket->OnConnect(nErrorCode);

        break;

    case FD_CLOSE:

        pSocket->OnClose(nErrorCode);

        break;

    }

}

以上就实现了套接字的创建及窗口建立,以及消息处理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值