本帖最后由 VisualEleven 于 2012-05-26 10:32:04 编辑

解决方案 »

  1.   

    代码发:[email protected]只看上面这些也不能判定是哪个地方出了问题。可能是其他地方
      

  2.   

    检查是不是线程同步问题举例就WSASend后SetEvent是有问题的
    由于WSASend是异步,此时不一定完成发送数据,
    最好将SetEvent放到GetQueuedCompletionStatus里PER_HANDLE_DATA里各自只有一个收发PER_IO_OPERATION_DATA,必然要做很多同步工作
    倒不如弄个收发队列,需要收发时,就申请一个新的PER_IO_OPERATION_DATA如果自己搞不定,上传代码,等大牛解决吧。
      

  3.   

    一般来说,malloc返回空,并不是因为内存耗尽,而是堆被破坏了.你应该首先从堆块越界上找原因。
      

  4.   

    我的代码是ATL代码,在我的IOCP的ProcessIO里面,我对PerIOData添加了是否越界的判断,没有找到越界的问题,还有就是SetEvent是保证包是按顺序发送的,即使是弄个收发队列,还是要使用SetEvent类似的方法的!会不会是组件对象不能跨线程呢,我的组件对象都是Both模型呀,支持多线程中的调用的!
      

  5.   

    这是我的ProcessIO源码:
    UINT WINAPI CServerSocket::ProcessIO(LPVOID lpParam)
    {
     ::CoInitializeEx(NULL,COINIT_MULTITHREADED);
     //::CoInitialize(NULL);
     ServerSocketStruct*ss=(ServerSocketStruct*)lpParam; 
     CServerSocket*m_pServer=ss->m_pServer;
     HANDLE m_Tread=ss->m_Thread;
     delete ss;
     HANDLE CompletionPort = m_pServer->CompletionPort;
     DWORD BytesTransferred;
     LPPER_HANDLE_DATA PerHandleData;
     LPOVERLAPPED lpOverlapped;
     LPPER_IO_OPERATION_DATA PerIoData;
     DWORD Flags = 0; 
         DWORD dwRecv = 0;
     VARIANT_BOOL IsOk;
     while(true)
     {
     if(0 == GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,(PULONG_PTR)&PerHandleData,(LPOVERLAPPED*)&lpOverlapped,INFINITE))
     {
     if( (GetLastError() == WAIT_TIMEOUT) || (GetLastError() == ERROR_NETNAME_DELETED) )
     {
     PerIoData = (LPPER_IO_OPERATION_DATA)CONTAINING_RECORD(lpOverlapped,PER_IO_OPERATION_DATA,Overlapped);
     if(PerHandleData==NULL) 
     {
     ::GlobalFree(PerIoData);
     SetEvent(m_Tread);
     ::CoUninitialize();
    #ifdef _DEBUG
     TRACE("接受线程退出\n");
    #endif
     return 0;
     }
     IsOk=VARIANT_FALSE;
     if(PerHandleData->g_pUser!=NULL) 
     {
     m_pServer->Fire_OnClientQuit((INetUser*)PerHandleData->g_pUser);
     CNetUsers*cUsers=(CNetUsers*)m_pServer->pUsers;
     cUsers->RemoveUser((INetUser*)PerHandleData->g_pUser,&IsOk);
                         PerHandleData=NULL; 
     }
     continue;
     }
     }
     PerIoData = (LPPER_IO_OPERATION_DATA)CONTAINING_RECORD(lpOverlapped,PER_IO_OPERATION_DATA,Overlapped);
     if(PerHandleData==NULL) 
     {
     ::GlobalFree(PerIoData);
     SetEvent(m_Tread);
      ::CoUninitialize();
    #ifdef _DEBUG
     TRACE("接受线程退出\n");
    #endif
    return 0;
     }
     // 说明客户端已经退出
     if(BytesTransferred == 0)
     {
     IsOk=VARIANT_FALSE;
         if(PerHandleData->g_pUser!=NULL) 
     {
         CNetUsers*cUsers=(CNetUsers*)m_pServer->pUsers;
     m_pServer->Fire_OnClientQuit((INetUser*)PerHandleData->g_pUser);
     cUsers->RemoveUser((INetUser*)PerHandleData->g_pUser,&IsOk);
     }
     continue;
     }
     if(PerIoData->BytesSend==0)
     {
                 m_pServer->sis.NotifyInBytes(BytesTransferred);
     CTime time=CTime::GetCurrentTime(); 
     SYSTEMTIME systime;
     time.GetAsSystemTime(systime);//转成systime
     double dtime;
     SystemTimeToVariantTime(&systime,&dtime);
     PerHandleData->RecentTime=dtime;
     PerIoData->BytesRecv+=BytesTransferred;
     if(PerIoData->BytesLength==0)
     {
     if(PerIoData->BytesRecv<8)
     {
     ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
     PerIoData->BytesPin+=BytesTransferred;
     PerIoData->DataBuf.buf = PerIoData->Buffer+PerIoData->BytesPin;
     PerIoData->DataBuf.len = MAX_BUFFER_SIZE-PerIoData->BytesPin;
     WSARecv(PerHandleData->Socket, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); 
     continue;
     }
     char*buffer=(char*)PerIoData->Buffer+PerIoData->BytesFrom; //操作同一块内存区域
     LONG BufferSize;
     char*ca=(char*)&BufferSize;
     memcpy(ca,buffer+4,4);
     PerIoData->BytesLength=BufferSize+PACKAGE_HEADER;
     }
     bool IsValid=true;
     if(PerIoData->BytesRecv>=PerIoData->BytesLength)
     {
    int ValidPin=PerIoData->BytesPin+BytesTransferred;
    while(TRUE)
    {
    char*buffer=(char*)PerIoData->Buffer+PerIoData->BytesFrom; //操作同一块内存区域
    LONG BufferSize;
    char*ca=(char*)&BufferSize;
    memcpy(ca,buffer+4,4);
    BufferSize+=PACKAGE_HEADER;
    if(PerIoData->BytesFrom+BufferSize>ValidPin)
    {
    for(int k=PerIoData->BytesFrom;k<ValidPin;k++)
    {
    PerIoData->Buffer[k-PerIoData->BytesFrom]=PerIoData->Buffer[k];
    }
    PerIoData->BytesLength=BufferSize;
    PerIoData->BytesRecv=ValidPin-PerIoData->BytesFrom;
    PerIoData->BytesPin=PerIoData->BytesRecv;
    PerIoData->BytesFrom=0;
    break;
    }
    IDataPackage*pdr;
    CDataPackage::_CreatorClass::CreateInstance(NULL, __uuidof(IDataPackage), (void**)&pdr);
    BYTE*data=new BYTE[BufferSize];
    if(data!=NULL)
    {
    memcpy(data,buffer,BufferSize);
    CDataPackage*cPack=(CDataPackage*)pdr;
    cPack->buffer=data;
    IsValid=m_pServer->NotifyAcceptDataPackage(PerHandleData,pdr);
        if(!IsValid)
    {
    pdr->Release(); 
    break;
    }
    }
    pdr->Release();
    PerIoData->BytesFrom+=BufferSize;
    BufferSize=PerIoData->BytesPin+BytesTransferred-PerIoData->BytesFrom;
    if(BufferSize<PACKAGE_HEADER)
    {
    for(int k=0;k<BufferSize;k++)
    {
    PerIoData->Buffer[k]=PerIoData->Buffer[PerIoData->BytesFrom+k];
    }
    PerIoData->BytesLength=0;
    PerIoData->BytesRecv=BufferSize;
    PerIoData->BytesPin=BufferSize;
    PerIoData->BytesFrom=0;
    break;
    }
    }
     }
     else
     {
    PerIoData->BytesPin+=BytesTransferred;
     }
     if(!IsValid) continue;
     // 取得数据并处理
     // 继续向 socket 投递WSARecv操作
     ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
     PerIoData->DataBuf.buf = PerIoData->Buffer+PerIoData->BytesPin;
     PerIoData->DataBuf.len = MAX_BUFFER_SIZE-PerIoData->BytesPin;
     WSARecv(PerHandleData->Socket, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL);  
     }
     else 
     {
     m_pServer->sis.NotifyOutBytes(BytesTransferred);
     if(PerHandleData->g_pServer==m_pServer)
     {
     if(BytesTransferred+PerIoData->BytesFrom<PerIoData->BytesSend)
     {
     ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
     PerIoData->DataBuf.buf=PerIoData->Buffer+BytesTransferred+PerIoData->BytesFrom;
     PerIoData->DataBuf.len=PerIoData->BytesSend-(BytesTransferred+PerIoData->BytesFrom);
     PerIoData->BytesSend=PerIoData->BytesSend-(BytesTransferred+PerIoData->BytesFrom);
                         PerIoData->BytesFrom+=BytesTransferred;
     DWORD SendBytes;
     WSASend(PerHandleData->Socket,&(PerIoData->DataBuf),1,&SendBytes,0,&(PerIoData->Overlapped),NULL);
     }
     else 
     {
     INetUser*pUser=(INetUser*)PerHandleData->g_pUser;
     CNetUser*cUser=(CNetUser*)pUser;
     cUser->SendNextPackage();
     }
     }
     }
     } 
     SetEvent(m_Tread);
     ::CoUninitialize();
    #ifdef _DEBUG
     TRACE("接受线程退出\n");
    #endif
     return 0;
    }