在windows网络编程中,关于完成端口部分中:
定义结构:
typedef struct{
    OVERLAPPED Overlapped;
WSABUF DataBuf;
    char Buffer[DATABUF_SIZE];
    int OperationType;
    // other useful information
}PER_IO_DATA;在listen线程中:
当有client连接上来后进行I/O投递,
在WSARecv之前执行:
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATABUF_SIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;  
PerIoData->OperationType = RECV_POSTED;
Flags = 0;
WSARecv(acceptSocket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,&(PerIoData->Overlapped), NULL);在工作线程中:
GetQueuedCompletionStatus(CompletionPort,&ByteTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&Overlapped,INFINITE);PerIoData = CONTAINING_RECORD((LPOVERLAPPED *)&Overlapped,PER_IO_DATA,Overlapped);
很奇怪的是,此时PerIoData中OperationType没有数据了,我认为应该是RECV_POSTED啊!

解决方案 »

  1.   

    可能是你通过Overlapped得到PER_IO_DATA的时候出了问题!
      

  2.   

    你的意思是我通过这个宏CONTAINING_RECORD得到PerIoData有问题?
    可是我看windows网络编程上就是这样的啊!
      

  3.   

    如果不是RECV_POSTED就不要管他。
      

  4.   

    CIOCP_Server* pThis = reinterpret_cast<CIOCP_Server*>(WorkContext);
    ASSERT(pThis);    HANDLE hCompletionPort = pThis->m_hCompletionPort;    
        DWORD dwIoSize;
        LPOVERLAPPED lpOverlapped;
    OVERLAPPEDPLUS * lpOverlappedPlugs;
        ClientContext* lpClientContext;
    BOOL bErro; while(1)
    {
    bErro = FALSE;
    lpClientContext = NULL;
    lpOverlapped = NULL;
    lpOverlappedPlugs = NULL;
    TRACE2("while : %s-%d ThreadPoolFunc\n",__FILE__,__LINE__);

    // Get a completed IO request.
    BOOL bIORet = GetQueuedCompletionStatus(
    hCompletionPort,
    &dwIoSize,
    (LPDWORD) &lpClientContext,
    &lpOverlapped, INFINITE);
    DWORD dwIOError = GetLastError();
            if (!bIORet && dwIOError != WAIT_TIMEOUT )//
    {
    if (lpClientContext)
    pThis->RemoveStaleClient(lpClientContext, FALSE);
    continue;
    bErro = TRUE;
    }

    lpOverlappedPlugs = (OVERLAPPEDPLUS *)lpOverlapped;
    int ret = 0;
    if(!bErro)
    {
    if(bIORet && NULL != lpOverlapped && NULL != lpClientContext)
    {
    if(lpOverlappedPlugs->m_ioType == IORead)
    {
    if(dwIoSize == 0)
    {
    if (lpClientContext)
    pThis->RemoveStaleClient(lpClientContext, FALSE);
    continue;
    }
    lpClientContext->m_translate = dwIoSize;
    ret = lpClientContext->DelWithResData();
    }else
    if(lpOverlappedPlugs->m_ioType == IOInitialize)
    {
    ret = 1;
    }else
    {
    ret = 0;
    }
    }
    }
    //delete plug pre call
    if(bIORet && NULL == lpOverlapped && NULL == lpClientContext) 
    {
    break;
    }
    OVERLAPPEDPLUS * lpPrePlugs = NULL;
    if(! bErro && ret ) 
    {
    // issue a read request 
    lpPrePlugs = lpClientContext->m_preCall;
    OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IORead); 
    ULONG ulFlags = MSG_PARTIAL;
    lpClientContext->m_preCall = pOverlap;

    UINT nRetVal = WSARecv(lpClientContext->m_Socket, 
    &lpClientContext->m_wsaInBuffer,
    1,
    &dwIoSize, 
    &ulFlags,
    &pOverlap->m_ol, 
    NULL);

    if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) 
    {
    pThis->RemoveStaleClient( lpClientContext, FALSE );
    }
    }

    if(lpOverlappedPlugs && ret)
    {
    if(lpPrePlugs == lpOverlappedPlugs)
    {
    if(lpPrePlugs->m_ioType == IOInitialize || 
    lpPrePlugs->m_ioType == IORead)
    delete lpPrePlugs; // from previous call
    }
    }

    }
      

  5.   

    不能不管啊,因为我发现DataBuf中buf的内容也是错误的,按理说我接收到的内容应该是放在DataBuf的buf中啊!
      

  6.   

    PerIoData应该在堆上分配内存
    否则可能在工作线程中该内存有可能失效
    从而得到不正确的值
      

  7.   

    这个问题解决了,原来是我的笔误造成的,在
    GetQueuedCompletionStatus(CompletionPort,&ByteTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&Overlapped,INFINITE);
    这句中,应该为:(LPOVERLAPPED *)&PerIoData不过现在又有一个新问题了,在结构PER_IO_DATA中,为什么每次使用前都不用对Buffer清零啊?