服务端是IOCP模型,是我工作者线程处理时出问题了吗?工作者线程如下:
DWORD WINAPI CMySvr::WorkerThread(void *lpPara)
{
_stThreadParam_ *pParam =(_stThreadParam_ *)lpPara;
HANDLE CompletionPort=pParam->completePort;
CMySvr *pSvr = pParam->pSvr;    DWORD BytesTransferred;
LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
IO_DATA*   data;         
DWORD SendBytes, RecvBytes;
DWORD Flags;

while(TRUE)
{
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &data, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
return 0;
}

// 检查数据传送完了吗
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);

if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
return 0;
}

GlobalFree(PerHandleData); //释放内存块。您必须传给该函数一个内存句柄。
GlobalFree(data);
continue;
}     
if(data->opCode == IO_READ)
{
pSvr->RecvData(data,PerHandleData->Socket);   //对接收到的信息进行处理,处理时会WSASend()
}
else if(data->opCode == IO_WRITE)
{
data->opCode = IO_READ; 
RecvBytes = 0;
Flags = 0;
data->wsabuf.buf = data->Buffer,
ZeroMemory(data->wsabuf.buf,MAX_BUFF_SIZE);
data->Overlapped.Internal = 0;
data->Overlapped.InternalHigh = 0;
data->Overlapped.Offset = 0;
data->Overlapped.OffsetHigh = 0;
data->Overlapped.hEvent = NULL;
data->wsabuf.len = MAX_BUFF_SIZE;
int nRet = WSARecv(              
PerHandleData->Socket,
&data->wsabuf, 1, &RecvBytes,
&Flags,
&data->Overlapped, NULL);         //继续接收数据
if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != GetLastError()) )
{
cout << "WASRecv Failed::Reason Code::"<< GetLastError() << endl;
closesocket(PerHandleData->Socket);
delete data;
continue;
}
}
}
return 0;
}

解决方案 »

  1.   

    IO_DATA*  data;   指向那里的? 这是个野指针
    GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, 
    (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &data, INFINITE) &data , 不出错才怪!
      

  2.   

    if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
    (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &Overlapped, INFINITE) == 0)
    {
    printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
    continue;
    }
    data=(IO_DATA *)Overlapped;
    这样可以吗?
      

  3.   

    LPOVERLAPPED Overlapped;  
    还是个野指针
    改成  POVERLAPPED Overlapped;  
      

  4.   

    错了, 是 OVERLAPPED Overlapped;  
      

  5.   

    LPOVERLAPPED Overlapped;  
    是因为没初始化吗?
    那改成LPOVERLAPPED Overlapped=NULL;可以吗?
      

  6.   

    LPOVERLAPPED Overlapped = new  OVERLAPPED;  记得要 
    delete  Overlapped ;
      

  7.   

    我现在对工作者线程的理解是:处理投递的I/O操作,为下一个重叠调用建立I/O操作数据。
      

  8.   

    处理本次I/0 操作,  投递下一次I/0 操作请求(WSARecv)
      

  9.   

    所以说我上面的处理流程就有问题,更改如下:
    DWORD WINAPI CMySvr::WorkerThread(void *lpPara)
    {
    _stThreadParam_ *pParam =(_stThreadParam_ *)lpPara;
    HANDLE CompletionPort=pParam->completePort;
    CMySvr *pSvr = pParam->pSvr;    DWORD BytesTransferred;
    LPOVERLAPPED Overlapped = new OVERLAPPED;
    LPPER_HANDLE_DATA PerHandleData;
    IO_DATA*   data;         
    DWORD SendBytes, RecvBytes;
    DWORD Flags;

    while(TRUE)
    {
    //在这里检查完成端口部分的数据buf区,数据来了吗?
    // 这个函数参数要看说明,
    // data 就是从管子流出来的数据,
    //PerHandleData 也是从管子里取出的,是何时塞进来的,
    //就是在建立第2次createIocompletionPort时

    if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
    (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &Overlapped, INFINITE) == 0)
    {
    printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
    closesocket(PerHandleData->Socket);
    ZeroMemory(&data->cltInfo,sizeof(_stCltInfo_));
    continue;
    }
    data=(IO_DATA *)Overlapped;

    // 检查数据传送完了吗
    if (BytesTransferred == 0)
    {
    printf("Closing socket %d\n", PerHandleData->Socket);

    if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
    {
    printf("closesocket() failed with error %d\n", WSAGetLastError());
    return 0;
    }
    printf("传送完了???????????????????????????????????\n");

    GlobalFree(PerHandleData); //释放内存块。您必须传给该函数一个内存句柄。
    GlobalFree(data);
    delete Overlapped;
    continue;
    }
    data=CONTAINING_RECORD(&data->Overlapped,IO_DATA,Overlapped);
    if(data->opCode == IO_READ)
    {
    pSvr->RecvData(data,PerHandleData->Socket);
    } data->opCode = IO_READ; 
    RecvBytes = 0;
    Flags = 0;
    ZeroMemory(&(data->Overlapped),sizeof(OVERLAPPED));
    data->wsabuf.buf = data->Buffer;
    data->wsabuf.len = MAX_BUFF_SIZE;
    int nRet = WSARecv(
    PerHandleData->Socket,
    &data->wsabuf, 1, &RecvBytes,
    &Flags,
    &data->Overlapped, NULL);
    if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != GetLastError()) )
    {
    cout << "WASRecv Failed::Reason Code::"<< GetLastError() << endl;
    closesocket(PerHandleData->Socket);
    delete data;
    delete Overlapped;
    continue;
    }
    }
    return 0;
    }