none
极其郁闷的IOCP程序 RRS feed

  • 常规讨论

  • 有个错误的IOCP完成端口程序,有几个凝问,请高手帮忙找下

    BOOL CMyIOCP::Start(int Port, int NumOfCpu)//要传入二个参数,端口号和CPU个数
    {
      h_Listen = CreateThread(NULL, 0, ListenThreadProc, (void*)this, 0, NULL);//监听线程
     if(NULL == h_Listen)
     {
      AfxMessageBox(_T("1"));
      return false;
     }

     h_Logic  = CreateThread(NULL, 0, LogicThreadProc, (void*)this, 0, NULL);//逻辑线程
     if(NULL == h_Logic)
     {
      AfxMessageBox(_T("2"));
      return false;
     }

     StartUpIoThread();//IO线程

     return true;
    }


    DWORD WINAPI CMyIOCP::ListenThreadProc(LPVOID lpParam)
    {
     CMyIOCP *pthis = reinterpret_cast<CMyIOCP*>(lpParam);

     pthis->m_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
     if(INVALID_SOCKET == pthis->m_ListenSocket)
     {
      int r = WSAGetLastError();
      AfxMessageBox(_T("3"));
     }

     pthis->h_CompletionPort = CreateIoCompletionPort((HANDLE)pthis->m_ListenSocket, NULL, 0, 0);
     if(NULL == pthis->h_CompletionPort)
     {
      AfxMessageBox(_T("4"));
     }

     SOCKADDR_IN sr;
     sr.sin_addr.S_un.S_addr = INADDR_ANY;
     sr.sin_family = AF_INET;
     sr.sin_port = htons(6000);
     if(bind(pthis->m_ListenSocket, (SOCKADDR*)&sr, sizeof(sr)) == SOCKET_ERROR)
     {
      AfxMessageBox(_T("5"));
     }

     if(listen(pthis->m_ListenSocket, 5) == SOCKET_ERROR)
     {
      AfxMessageBox(_T("6"));
     }

     pthis->m_event = WSACreateEvent();

     if(WSAEventSelect(pthis->m_ListenSocket ,pthis->m_event, FD_ACCEPT) == SOCKET_ERROR)
     {
      AfxMessageBox(_T("7"));
     }

     while(true)
     {
      if(WSAWaitForMultipleEvents(1, &pthis->m_event ,FALSE, WSA_INFINITE, FALSE) == WSA_WAIT_FAILED)
      {
       AfxMessageBox(_T("8"));
      }
      WSANETWORKEVENTS even;
      BOOL nRet = WSAEnumNetworkEvents(pthis->m_ListenSocket, pthis->m_event, &even);
      if(nRet == WSA_WAIT_TIMEOUT)
      {
       AfxMessageBox(_T("9"));
       continue;
      }

      if(even.lNetworkEvents & FD_ACCEPT)
      {
       SOCKADDR_IN sdr;
       int len = sizeof(sdr);
       pthis->m_AcceptSocket = WSAAccept(pthis->m_ListenSocket, (SOCKADDR*)&sdr, &len, NULL, NULL);
       if(INVALID_SOCKET == pthis->m_AcceptSocket)
       {
        AfxMessageBox(_T("10"));
       }

       if(CreateIoCompletionPort((HANDLE)pthis->m_AcceptSocket, pthis->h_CompletionPort, NULL, 0) == NULL)//socket和端口关联
       {
        AfxMessageBox(_T("11"));
       }
       if(PostQueuedCompletionStatus(pthis->h_CompletionPort, pthis->dwNumberOfBytesTransferred, pthis->m_ListenSocket, pthis->lpOverlapped) == 0)//向完成端口投递消息
       {
        AfxMessageBox(_T("12"));
       }
      }
     }
     pthis->StartUpIoThread();
     return 0;
    }

    BOOL CMyIOCP::StartUpIoThread(void)
    {
     h_IO     = CreateThread(NULL, 0, IOThreadProc, (void*)this, 0, NULL);
     if(NULL == h_IO)
     {
      AfxMessageBox(_T("13"));
      return false;
     }
     return 0;
    }

    DWORD WINAPI CMyIOCP::IOThreadProc(LPVOID lpParam)
    {
     CMyIOCP *pthis = reinterpret_cast<CMyIOCP*>(lpParam);
     if(pthis)
     {
      while(true)
      {
       GetQueuedCompletionStatus(pthis->h_CompletionPort, pthis->lpNumberOfBytes, NULL, pthis->lpOverlapp, INFINITE);//从完成端口取消息,,,这行有错误,,,
       AfxMessageBox(_T("14"));
       if(WSARecv(pthis->m_AcceptSocket, &pthis->m_Buf, 1, pthis->m_Data, 0, NULL, NULL) == SOCKET_ERROR)
       {
        AfxMessageBox(_T("15"));
       }
      }
     }
     return 0;
    }


    DWORD WINAPI CMyIOCP::LogicThreadProc(LPVOID lpParam)
    {
     CMyIOCP *pthis = reinterpret_cast<CMyIOCP*>(lpParam);
     return 0;
    }

    GetQueuedCompletionStatus(pthis->h_CompletionPort, pthis->lpNumberOfBytes, NULL, pthis->lpOverlapp, INFINITE)和CreateIoCompletionPort((HANDLE)pthis->m_AcceptSocket, pthis->h_CompletionPort, NULL, 0)函数的第三个参数是完成键,我不知道怎样用,,,请大家指点


    xiao
    2011年2月22日 11:12

全部回复

  • 这里有个IOCP的例子程序,您可以参考一下,希望对你有帮助http://blog.csdn.net/VisualEleven/archive/2010/12/21/6088590.aspx
    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    2011年2月23日 3:16
    版主
  • 第三个参数是一个附带信息,GetQueuedCompletionStatus取IO完成包时会返回的。例如你想给绑定在完成端口上套接字关联一些信息,你可以定义一个结构体,将结构数据的指针值作为第三个参数传进去就可以了。
    2011年2月23日 8:08
  • CreateIoCompletionPort是不是相当下面这个模型呢:
    张三(ListenSocket)在某个地方(CompletionPort)放置了某些东西并画了一张图(CompletionKey)。

    PostQueuedCompletionStatus模型:
    李四(AcceotSocket)在某个地方(CompletionPort)按图(CompletionKey)找东西。

    哪PostQueuedCompletionStatus的第四个参数lpOverlapped 就没法解释了。


    xiao
    2011年2月23日 11:32
  •  

    以下是我对使用IO完成端口(IO完成端口是用于异步IO模型的)步骤的理解,希望对你有所帮助,有问题相互探讨。具体步骤如下:

    1、CreateIoCompletionPort创建完成端口内核对象;

    2、CreateIoCompletionPort将其它内核对象(例如,文件句柄,socket句柄)与完成端口绑定,同时绑

    定时可以关联一个有意义的CompletionKey,这个关联值可以有也可以没有,视你的程序而定;

    3、在与完成端口绑定的内核对象上投递IO操作。例如在以FILE_FLAG_OVERLAPPED模式打开的文件句柄上

    通过ReadFile投递IO请求,ReadFile函数需要传递一个OVERLAPPED结构的指针,通常是通过继承

    OVERLAPPED结构体来存放我们每次IO请求需要的自定义数据的。例如

    struct CustomizedOverlapped: public OVERLAPPED

    {

       unsigned char fileBuff[512];

    }

    4、GetQueuedCompletionStatus获取IO完成包,IO完成包反映了向完成端口关联的内核对象上投递的IO

    请求的完成情况,例如以ReadFile读文件为例,GetQueuedCompletionStatus的返回值为非0表示

    ReadFile文件操作成功,否则操作失败。GetQueuedCompletionStatus返出的三个参数lpNumberOfBytes

    表示实际ReadFile读取的文件字节数。lpCompletionKey表示完成端口与文件句柄关联时指定的完成键值

    ,它是否有意义视程序而定,但是一旦通过CreateIoCompletionPort关联后每次

    GetQueuedCompletionStatus返回的lpCompletionKey值都是不会再变化的,但是lpCompletionKey是指针

    值,它指向的内存内容可以变的。lpOverlapped表示ReadFile投递请求时指定的Overlapped结构体指针,比如传递CustomizedOverlapped结构体指针,那么就可以从fileBuff中获取ReadFile读取到的文件数据;

    5、PostQueuedCompletionStatus向完成端口发送IO完成包。例如可以通过PostQueuedCompletionStatus发送IO完成包通知等待GetQueuedCompletionStatus结果的工作线程退出等。

    2011年2月24日 2:57
  • CreateIoCompletionPort函数是关联完成端口和一个或多个句柄,当一个和完成端关联的文件句柄执行I/O操作,当I/O操作完成时投递完成消息到FIFO队列,
    完成键的描述是:The per-file completion key that is included in every I/O completion packet for the specified file(包括于每份I/O完成包指定的文件中),这句没搞明白.

    PostQueuedCompletionStatus 的作用是投递完成包到完成端口队列,四个参数都是in类型的,直接传到GetQueuedCompletionStatus.

    GetQueuedCompletionStatust和多线程关联起来,形成FILO的堆栈,注意到第四个参数一般是自定义的Overlapped结构体,这里就有一个问题:系统怎样知该向哪个数据成员传递数据?


    xiao
    2011年2月24日 12:18
  • 1、CreateIoCompletionPort关联的完成键的解释:The per-file completion key that is included in every I/O completion packet for the specified file。就是说的GetQueuedCompletionStatus每次获得的IO完成包都会包括这个值,也就是GetQueuedCompletionStatus中的第三个参数 lpCompletionKey表示的值;

     

    2、比如ReadFile以OVERLAP的方式读取文件时,ReadFile函数定义如下:

    BOOL WINAPI ReadFile(
     __in     HANDLE hFile,
     __out     LPVOID lpBuffer,
     __in     DWORD nNumberOfBytesToRead,
     __out     LPDWORD lpNumberOfBytesRead,
     __in     LPOVERLAPPED lpOverlapped
    );
    

    其中lpBufferlpOverlapped指向的自定义结构的数据成员指向的同一个内存区域。这样GetQueuedCompletionStatus取IO完成包时,通过获得的Overlapped结构体指针就可以取读取到的文件数据了。


    2011年2月25日 6:43
  • 终于明白了。

    谢谢你的指点


    xiao
    2011年2月25日 12:18