一个完成端口写的服务器,当客户端不停的连接服务器 然后断开 这样重复大概几个小时后 CreateIoCompletionPort函数调用失败 请大家分析一下是什么原因

解决方案 »

  1.   

    可为什么有的大型服务器却可以呢 象WEB服务器也是连接/断开很频繁
      

  2.   

    失败的时候,GetLastError() 返回什么错误?
      

  3.   

    断开后有没有 CloseHanle 啊。
      

  4.   

    哦断开还要CloseHanle 吗 可就一个完成端口啊
      

  5.   

    确定是连接上了吗?
    如果你是用AcceptEx的话建议你改成WSAAccept,因为AcceptEx如果Client没有发数据过来会停在那!WSAAccept是同步的,要用一个线程来不停那循环!
      

  6.   

    完成端口用AcceptEx效率应该更加高些的,而且AcceptEx也可以通过参数设置,不接收数据的
      

  7.   

    我这个服务器是从网上下载的代码
    相信大家都看到过
    unsigned CIOCPServer::ListenThreadProc(LPVOID lParam)
    {
    CIOCPServer* pThis = reinterpret_cast<CIOCPServer*>(lParam); WSANETWORKEVENTS events;
    memset( &events,0,sizeof(WSANETWORKEVENTS) );
    while(1)
    { if (WaitForSingleObject(pThis->m_hKillEvent, 10) == WAIT_OBJECT_0)
                break;
    DWORD dwRet;
    dwRet = WSAWaitForMultipleEvents(1,
     &pThis->m_hEvent,
     FALSE,
     150,//100
     FALSE); if (dwRet == WSA_WAIT_TIMEOUT)
    continue; int nRet = WSAEnumNetworkEvents(pThis->m_socListen,
     pThis->m_hEvent,
     &events);

    if (nRet == SOCKET_ERROR)
    {
    //TRACE(_T("WSAEnumNetworkEvents error %ld\n"),WSAGetLastError());
    CString str;
    str.Format("WSAEnumNetworkEvents error %ld",WSAGetLastError());
    pThis->m_pServerIOMgr->m_LogFile.MsgOut(str); break;
    } if (events.lNetworkEvents & FD_ACCEPT)
    {
    if (events.iErrorCode[FD_ACCEPT_BIT] == 0)
    {
    pThis->OnAccept();
    }
    else
    {
    //TRACE(_T("Unknown network event error %ld\n"),WSAGetLastError());
    CString str;
    str.Format("Unknown network event error %ld",WSAGetLastError());
    pThis->m_pServerIOMgr->m_LogFile.MsgOut(str); break; } }
    } return 0;
    }void CIOCPServer::OnAccept()
    {
    SOCKADDR_IN SockAddr;
    SOCKET clientSocket;

    int nRet;
    int nLen; nLen = sizeof(SOCKADDR_IN);
    clientSocket = accept(m_socListen,
        (LPSOCKADDR)&SockAddr,
    &nLen);  if (clientSocket == SOCKET_ERROR)
    {
    nRet = WSAGetLastError();
    if (nRet != WSAEWOULDBLOCK)
    {
    //TRACE(_T("accept() error\n"),WSAGetLastError());
    CString str;
    str.Format("accept() error %ld",nRet);
    m_pServerIOMgr->m_LogFile.MsgOut(str); return;
    }
    }
    ClientContext* pContext = AllocateContext();//控制台死掉的话 被分配的ClientContext不能被清除 直到TCP机制检测到和控制台连接断开(???)    pContext->m_Socket = clientSocket;
    pContext->m_wsaInBuffer.buf = (char*)pContext->m_byInBuffer;
    pContext->m_wsaInBuffer.len = sizeof(pContext->m_byInBuffer);
    /*
    const char chOpt = 1;
    int nErr = setsockopt(pContext->m_Socket, IPPROTO_TCP, TCP_NODELAY, &chOpt, sizeof(char));
    if (nErr == -1)
    {
    TRACE(_T("setsockopt() error\n"),WSAGetLastError());
    return;
    }
    */ int nZero = 16*1024;
    setsockopt(pContext->m_Socket,SOL_SOCKET,SO_RCVBUF,(char *)&nZero,sizeof(nZero) ); //为新的套接字分配完成端口
    if ( !AssociateSocketWithCompletionPort(clientSocket, m_hCompletionPort, (DWORD) pContext) )//这个地方ssociateSocketWithCompletionPort  返回FALSE 然后客户端连接出现10061错误
        {
            delete pContext;
    pContext = NULL;        closesocket( clientSocket );
            closesocket( m_socListen );
    CString str;
    str.Format("AssociateSocketWithCompletionPort Error %ld",::GetLastError());
    m_pServerIOMgr->m_LogFile.MsgOut(str);
            return;
        }
    g_ContextListCriticalSection.Lock();
    m_ContextList.AddTail(pContext);
    g_ContextListCriticalSection.Unlock();
    DWORD RecvBytes;
        DWORD Flags;
    Flags = 0;
        if (WSARecv(clientSocket, &(pContext->m_wsaInBuffer), 1, &RecvBytes, &Flags,
             &(pContext->Overlapped), NULL) == SOCKET_ERROR)
        {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
                return;
            }
        }}BOOL CIOCPServer::AssociateSocketWithCompletionPort(SOCKET socket, HANDLE hCompletionPort, DWORD dwCompletionKey)
    {
    HANDLE h = CreateIoCompletionPort((HANDLE) socket, hCompletionPort, dwCompletionKey, 0);
    return h == hCompletionPort;//我怀疑是这句错了
    }
      

  8.   

    上面的 “这个地方ssociateSocketWithCompletionPort  返回FALSE 然后客户端连接出现10061错误”应是下面这句
    “这个地方AssociateSocketWithCompletionPort  返回FALSE 然后客户端连接出现10061错误
      

  9.   

    断开后是否closesocket呢
    ----------------
    是的 已经调用closesocket了
      

  10.   

    BOOL CIOCPServer::AssociateSocketWithCompletionPort(SOCKET socket, HANDLE hCompletionPort, DWORD dwCompletionKey)
    {
              if(CreateIoCompletionPort((HANDLE) socket, hCompletionPort, dwCompletionKey, 0) == NULL)
               {
                   DWORD dwErr = GetLastError();
                   return FALSE;
                }   return TRUE;
    }    具体看一下dwErr,然后看下传入的参数是否有效
     
    }
      

  11.   

    这个写法挺新鲜,你能把你的源码发给我看看吗?
    或者给个网址!
    [email protected],这个也是我的msn,希望以后能联系!
      

  12.   

    GetLastError();得到错误码是0,CreateIoCompletionPort返回的是NULL,以前是CreateIoCompletionPort返回NULL时,我就closesocket( m_socListen );现在我把这句去掉了 让m_socListen 继续探听连接 后面的连接就能连接上了  但是大概连接次数有几十万时CreateIoCompletionPort就又返回NULL了 也就是有时CreateIoCompletionPort会返回NULL
      

  13.   

    TO  skyupsky(北方舞者) 我是从www.codeproject.com下载的 你找一找吧  找不到的话我再发给你
      

  14.   

    IoCompletionPort我正在学习关注中……