CSocet类的Receive函数是阻塞试的,如果没有接受到数据这个函数就不会返回了,整个程序就卡住了,有没有用来设置超时处理的函数,让Receive函数在一定时间内如果没有接受到数据就返回

解决方案 »

  1.   

    使用WSAAsyncSelect到某个HWND的消息或者用WSAEventSelect //设置Event
    WSAEVENT hDataEvent = WSA_INVALID_EVENT;
    hDataEvent = WSACreateEvent();
    ::WSAEventSelect(sm, hDataEvent, FD_READ | FD_CLOSE); //Event循环
    BOOL bQuitEvent = FALSE;
    while (!bQuitEvent)
    {
    int nReturnCode = ::WSAWaitForMultipleEvents(1, &hDataEvent, FALSE, INFINITE, FALSE); 
    if (nReturnCode == WSA_WAIT_EVENT_0)
    {
    WSANETWORKEVENTS wsaProcessEvents;
    ::WSAEnumNetworkEvents(sm, hDataEvent, &wsaProcessEvents);

    if (wsaProcessEvents.lNetworkEvents & FD_READ)
    // && (wsaProcessEvents.iErrorCode[FD_ACCEPT_BIT] == 0))
    { //接受数据
    /* DWORD dwSize;
    int nRet = ioctlsocket(*pInfo->s, FIONREAD, &dwSize);
    int nRecv;
    while(dwSize > 0)
    {
    char*  byRecv = new char [nRet];
    memset(byRecv, 0, nRet);
    nRecv = recv(sm, byRecv, nRet,0);
    delete []byRecv;
    nRet = ioctlsocket(sm, FIONREAD, &dwSize);
    }
    */ byte pBuff[1024]; 
    memset(pBuff, 0, 1024); int err = recv(sm, (char *)pBuff, 1024, 0);
    if ( err == SOCKET_ERROR || err == 0) 
    {
    main_window->AddInfo("接受数据失败,10秒钟后重试...");
    ::WSAEventSelect(sm, hDataEvent, 0);
    shutdown(sm, 2);
    closesocket(sm);
    ::WSACleanup();
    nTry ++;
    Sleep(10000);
    goto NEXTTRY;
    }CHECKNEXT:
    switch(pBuff[0])
    {
    case 0x6B: //edit code
    {
    break;
    }
    case 0x71:
    {
    }
    default:
    if (memcmp(pLoginSessionID1, pBuff, 4) == 0)
    {
    if (err > 4)
    {
    err -= 4;
    memcpy(pBuff, pBuff + 4, err);
    goto CHECKNEXT;
    }
    }
    else
    {//随机验证码错误
    ::WSAEventSelect(sm, hDataEvent, 0);
    shutdown(sm, 2);
    closesocket(sm);
    ::WSACleanup();
    main_window->AddInfo("随机验证码错误,请重新登陆");
    main_window->m_pMainThread = NULL;
    main_window->PostMessage(WM_COMMAND, IDC_LOGIN);
    return 1;
    }
    break;
    }
    }
    else if (wsaProcessEvents.lNetworkEvents & FD_CLOSE)
    // (wsaProcessEvents.iErrorCode[FD_ACCEPT_BIT] == 0)) 
    { //连接断开
    bQuitEvent = TRUE; ::WSAEventSelect(sm, hDataEvent, 0);
    shutdown(sm, 2);
    closesocket(sm); main_window->AddInfo("断开与主服务器的连接");
    break;
    }
    }
    }
      

  2.   

    //设置消息
    ::WSAAsyncSelect(*pInfo->s, pInfo->hWnd, RO_MSG, FD_READ|FD_CLOSE);
    LRESULT CRoGodDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    {
    LRESULT lrResult = CDialog::WindowProc(message, wParam, lParam); CString tmp, pProcess = "NONE";
    int nLen; switch(message)
    {
    case RO_MSG:
    {
    switch(LOWORD(lParam))
    {
    case FD_READ:
    {
    byte pBuff[RO_SOCKET_DATA_LENGTH];
    memset(pBuff, 0, RO_SOCKET_DATA_LENGTH); int err = recv(m_pSock, (char *)pBuff, RO_SOCKET_DATA_LENGTH, 0);
    if (err == SOCKET_ERROR)
    {
    tmp.Format("Main Thread Receive Data Error: %ld", WSAGetLastError());
    if (m_pNetData != NULL)
    {
    m_pNetData->AddMessage(tmp);
    }
    return lrResult;
    }
    break;
    case FD_CLOSE:
    ::WSAAsyncSelect(m_pSock, this->m_hWnd, 0, 0);
    shutdown(m_pSock, 2);
    closesocket(m_pSock);
    m_pSock = INVALID_SOCKET; pSkillPage.Clear();
    pRankPage.Clear(); rm1.flyer_used = FALSE;
    pStatusPage.Clear();
    Clear();

    PostMessage(WM_COMMAND, IDC_LOGIN); m_infolist.AddString("游戏服务器端关闭连接");
    m_infolist.SetCurSel(m_infolist.GetCount()-1); break;
    }
      

  3.   

    int optval =  60 * 1000;
    if(CSocket::setsockopt(SOL_SOCKET,SO_RCVTIMEO,
    (char * )&optval,sizeof(optval))==SOCKET_ERROR)
    {
    return NULL;
    }