我的客户端连发10条信息,在GetQueuedCompletionStatus之后先执行WSASendTo,那么这10条都能收到,如果把 WSASendTo注释掉,直接WSARecvFrom, 则只能收到第一条,而且每次我也将OVERLAPPED清空了,为什么呢?while(1)
{
bRet = GetQueuedCompletionStatus(pCServerDlg->g_hCompletionPort, // Completion Port
&BytesTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED*)&PerIoData, INFINITE);if(BytesTransferred==0) //EOF
{
closesocket(PerHandleData->hClntSock);
free(PerHandleData);
free(PerIoData);
continue;
}if (bRet || &PerIoData->overlapped )
{
if (bRet)
{
PerIoData->wsaBuf.len=BytesTransferred;
//由于WSASendTo的注释掉引出问题
//WSASendTo(pCServerDlg->g_hSocket, &(PerIoData->wsaBuf), 1, NULL, 0,(SOCKADDR*) &P
//erHandleData->clntAddr, sizeof(PerHandleData->clntAddr),NULL, NULL);// RECEIVE AGAIN
memset(&(PerIoData->overlapped), 0, sizeof(OVERLAPPED));
PerIoData->wsaBuf.len=BUFSIZE;
PerIoData->wsaBuf.buf=PerIoData->buffer;flags=0;
int fromlen =sizeof(PerHandleData->clntAddr);
dwNumberOfBytesRecvd = 0;PerIoData->overlapped.hEvent = pCServerDlg->g_hReadEvent;
PerIoData->overlapped.Offset = 0;
PerIoData->overlapped.OffsetHigh = 0;int iRet = WSARecvFrom(pCServerDlg->g_hSocket,&(PerIoData->wsaBuf),1,&dwNumberOfBytesRecvd,
&flags,(SOCKADDR*) &PerHandleData->clntAddr, &fromlen,&(PerIoData->overlapped), NULL);if (!iRet )
{
DWORD dwErrCode = GetLastError();
if( dwErrCode != ERROR_IO_PENDING )
{
//
}
else if( dwErrCode == ERROR_IO_PENDING )
{
WaitForSingleObject(PerIoData->overlapped.hEvent,INFINITE);pCServerDlg->HandleIncomingData(PerHandleData, PerIoData);
}
}
else
{
pCServerDlg->HandleIncomingData(PerHandleData, PerIoData);
}continue;
}
else
{
fprintf (stdout, "WorkThread Wait Failed\n");
//exit (1);
}
}

解决方案 »

  1.   

    上面的代码太长,可以简化为
    while(1)
    {
    bRet = GetQueuedCompletionStatus(pCServerDlg->g_hCompletionPort, // Completion Port
      &BytesTransferred, 
      (LPDWORD)&PerHandleData,
      (LPOVERLAPPED*)&PerIoData, // OVERLAPPED 
      INFINITE
      ); if(BytesTransferred==0) //EOF 
    {
    closesocket(PerHandleData->hClntSock);
    free(PerHandleData);
    free(PerIoData);
    continue;
    } PerIoData->wsaBuf.len=BytesTransferred;
    WSASendTo(pCServerDlg->g_hSocket, &(PerIoData->wsaBuf), 1, NULL, 0,(SOCKADDR*) &PerHandleData->clntAddr, 
    sizeof(PerHandleData->clntAddr),NULL, NULL); // RECEIVE AGAIN 
    memset(&(PerIoData->overlapped), 0, sizeof(OVERLAPPED));
    PerIoData->wsaBuf.len=BUFSIZE;
    PerIoData->wsaBuf.buf=PerIoData->buffer; flags=0;
    int fromlen =sizeof(PerHandleData->clntAddr); WSARecvFrom(pCServerDlg->g_hSocket,&(PerIoData->wsaBuf),1,NULL, 
    &flags,(SOCKADDR*) &PerHandleData->clntAddr, &fromlen,&(PerIoData->overlapped), NULL); pCServerDlg->HandleIncomingData(PerHandleData, PerIoData);
    }问题同上。
      

  2.   

    PerIoData->overlapped.hEvent = pCServerDlg->g_hReadEvent;
    PerIoData->overlapped.Offset = 0;
    PerIoData->overlapped.OffsetHigh = 0;
    ////////////////////////////////////////////////////不要关联事件pCServerDlg->g_hReadEvent,否则WSARecvFrom(pCServerDlg->g_hSocket,&(PerIoData->wsaBuf),1,NULL, 
    &flags,(SOCKADDR*) &PerHandleData->clntAddr, &fromlen,&(PerIoData->overlapped), NULL);
    将会触发事件,而不是完成端口
      

  3.   

    谢谢楼上的回复,不过请看我的第二段简化的代码,没有关联事件,也不行,为什么每次还得先执行 WSASendTo一次才能继续接收下面的数据呢?
    而且请注意我接收用的是刚开始定义的pCServerDlg->g_hSocket,而不是完成端口返回的PerHandleData->hClntSock,不过改过来也一样。这有什么区别吗?
      

  4.   

    另一端是不是有recv函数调用,被阻塞了?
      

  5.   

    多谢freemme(路在脚下)!还真是,我一直在服务器端检查,多谢提醒!能不能再回答一下为什么接收用pCServerDlg->g_hSocket,而用完成端口返回的socket(PerHandleData->hClntSock)会出现内存泄漏?
      

  6.   

    我的意思是:如果GetQueuedCompletionStatus返回,此时该用一开始与完成端口绑定的socket接收数据呢,还是该用GetQueuedCompletionStatus返回的socket接收数据?高手一句话就能说明白
      

  7.   

    我就问一个问题:如果GetQueuedCompletionStatus返回,此时该用一开始与完成端口绑定的socket接收数据呢,还是该用GetQueuedCompletionStatus返回的socket接收数据?