2011-09-07 82 views
0

我是IOCP的新手,并且在过去的几个星期里为此苦苦挣扎。 我粘贴了一些与IOCP相关的代码的核心部分。这可能无法完美执行,因为我剪下了一些部分以便于理解。 我在接收数据时很挣扎。对于工作线程中的wsarecv,wsarecv返回WSA_IO_PENDING错误代码,因此我调用WSAGetOverlappedResult来检查要完成的操作。 Twist来到这里,而是继续并在WSAGetOverlappedResult之后调用我的本地函数ProcessTelegramData,再次由另一个尝试调用ProcessTelegramData并且缓冲区值在其中无效的工作线程再次执行代码的相同部分(再次调用wsarecv)。 我无法理解 为什么当WSAGetOverlappedResult被调用时,另一个线程再次调用wsarecv,而 为什么缓冲区值变得无效?与IOCP一起使用时wsarecv的问题

unsigned LicTCPServer::WorkerThread(LPVOID lpParam) 
{ 
    //int nThreadNo = (int)lpParam; 
    LicTCPServer* pThis = reinterpret_cast<LicTCPServer*>(lpParam); 
    void *lpContext = NULL; 
    OVERLAPPED  *pOverlapped = NULL; 
    CClientContext *pClientContext = NULL; 
    DWORD   dwBytesTransfered = 0; 
    int nBytesRecv = 0; 
    int nBytesSent = 0; 
    DWORD    dwBytes = 0, dwFlags = 0; 

    //Worker thread will be around to process requests, until a Shutdown event is not Signaled. 
    while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0)) 
    { 
     BOOL bReturn = GetQueuedCompletionStatus(
      g_hIOCompletionPort, 
      &dwBytesTransfered, 
      (LPDWORD)&lpContext, 
      &pOverlapped, 
      INFINITE); 


     if (NULL == lpContext) 
     { 
      //We are shutting down 
      break; 
     } 

     //Get the client context 
     pClientContext = (CClientContext *)lpContext; 

     if ((FALSE == bReturn) /*|| ((TRUE == bReturn) && (0 == dwBytesTransfered))*/) 
     { 
      //Client connection gone, remove it. 
      pThis->RemoveFromClientListAndFreeMemory(pClientContext); 
      continue; 
     } 

     WSABUF *p_wbuf = pClientContext->GetWSABUFPtr(); 
     OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr(); 
     //printf("reached %d\n",pClientContext->GetOpCode()); 
     printf("Get Queued received\n"); 

     switch (pClientContext->GetOpCode()) 
     { 
     case OP_READ: 
      { 

       //Once the data is successfully received, we will print it. 
       //pClientContext->SetOpCode(OP_WRITE); 
       pClientContext->ResetWSABUF(); 

       dwFlags = 0; 
       //int a = recv(pClientContext->GetSocket(), p_wbuf->buf, p_wbuf->len, 0); 
       //Get the data. 

       if(WSARecv(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL) == SOCKET_ERROR) 
       { 
        if (WSAGetLastError() != WSA_IO_PENDING) 
        { 
         printf("Error occured at WSARecv()\n"); 
         return 0; 
        } 

       } 
       DWORD byteTr = 0; 

       WSAGetOverlappedResult(pClientContext->GetSocket(),p_ol,&byteTr,TRUE,&dwFlags); 

       if(byteTr > 0) 
       { 
        //doing some operatin on data received 
        printf("Process tele called\n"); 
        g_pLicServFunc->ProcessTelegramData(pClientContext->GetSocket(), p_wbuf->buf, byteTr); 
       } 

       if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError())) 
       { 
        //WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo); 

        //Let's not work with this client 
        //TBC 
        //RemoveFromClientListAndFreeMemory(pClientContext); 
       } 
      } 

      break; 

     case OP_WRITE: 

      char szBuffer[MAX_BUFFER_LEN]; 
      //Send the message back to the client. 
      pClientContext->SetOpCode(OP_READ); 


      pClientContext->SetTotalBytes(dwBytesTransfered); 
      pClientContext->SetSentBytes(0); 

      //p_wbuf->len = dwBytesTransfered; 

      dwFlags = 0; 
      DWORD temp; 
      //Overlapped send 
      printf("reached Going to send\n"); 
      //send(pClientContext->GetSocket(), p_wbuf->buf,p_wbuf->len, 0); 
      nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1, 
       &temp, dwFlags, p_ol, NULL); 

      if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError())) 
      { 
       //WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo); 

       //Let's not work with this client 
       //TBC 
       //RemoveFromClientListAndFreeMemory(pClientContext); 
      } 

      break; 

     default: 
      printf("reached to default\n"); 
      //We should never be reaching here, under normal circumstances. 
      break; 
     } // switch 
    } // while 

    return 0; 
} 

回答

0

我有一个WSARecv类似的问题,它总是排队等待IO完成队列,即使它立即成功。我不得不忽略表示成功的返回值,而是处理从GetQueuedCompletionStatus获得的排队结果。

相关问题