新套接字上的C ++ CreateIoCompletionPort

时间:2012-07-19 09:32:09

标签: c++ iocp

编辑:我猜测问题是我必须将容器中的OVERLAPPED或WSAOVERLAPPED与我的完成端口关联起来。这是对的吗?

当有人连接到我的服务器时,我可以获得IO完成。然后我在新套接字上使用CreateIoCompletionPort,并使用原始版本的完成端口。但是,当他们向我发送数据时,它不会被掀起。虽然,如果其他人连接,它仍然会被启动。我的问题是,为什么会发生这种情况?我还确保CreateIoCompletionPort返回与原始句柄相同的句柄。是什么给了什么?

编辑:

DWORD WINAPI worker_thread(LPVOID lpParam) {
 client_information_class *cicc = NULL;

 HANDLE        CompletionPort = (HANDLE)lpParam;
 ULONG_PTR     Key;
 DWORD          BytesTransfered;
 OVERLAPPED     *lpOverlapped = NULL;
 DWORD          error = NULL;
 while(1) {
      error = GetQueuedCompletionStatus(CompletionPort, &BytesTransfered, (PULONG_PTR)&Key, &lpOverlapped, 0);
      cicc = CONTAINING_RECORD ( lpOverlapped, client_information_class, ol );

      if ( error == TRUE ) {
           cout << endl << "IO TRIGGERED" << endl;
           switch ( cicc->operation ) {
                /*#define OP_ACCEPT        0
                  #define OP_READ          1
                  #define OP_WRITE         2*/
                case 0:{
                     if ( check_auth_progress ( cicc->client_socket , cicc->client_buff , BytesTransfered ) ) {
                          cout << "Client " << cicc->client_socket << " connected." << endl; 

                          client_information_class *k = NULL; 
                          SOCKADDR_STORAGE *LocalSockaddr=NULL, *RemoteSockaddr=NULL; 
                          int               LocalSockaddrLen,RemoteSockaddrLen; 

                          k = (client_information_class *)Key;
                          k->lpfnGetAcceptExSockaddrs( 
                               cicc->client_buff, 
                               cicc->client_len - ((sizeof(SOCKADDR_STORAGE) + 16) * 2), 
                               sizeof(SOCKADDR_STORAGE) + 16, 
                               sizeof(SOCKADDR_STORAGE) + 16, 
                               (SOCKADDR **)&cicc->LocalSockaddr, 
                               &cicc->LocalSockaddrLen, 
                               (SOCKADDR **)&cicc->RemoteSockaddr, 
                               &cicc->RemoteSockaddrLen 
                          );

                          client_information_class *cicc2 = NULL;
                          cicc2 = ( client_information_class *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(client_information_class) + (sizeof(BYTE) * 4096));
                          if (cicc2 == NULL) {
                               fprintf(stderr, "Out of memory!\n");
                          }

                          cicc2->client_socket = cicc->client_socket;
                          cicc2->client_socketaddr_in = cicc->client_socketaddr_in;
                          cicc2->LocalSockaddr = cicc->LocalSockaddr;
                          cicc2->LocalSockaddrLen = cicc->LocalSockaddrLen;
                          cicc2->RemoteSockaddr = cicc->RemoteSockaddr;
                          cicc2->RemoteSockaddrLen = cicc->RemoteSockaddrLen;

                          HANDLE hrc = CreateIoCompletionPort( (HANDLE)cicc2->client_socket, CompletionPort, (ULONG_PTR)cic,  0 ); 
                          if (hrc == NULL) { 
                               fprintf(stderr, "CompletionThread: CreateIoCompletionPort failed: %d\n", GetLastError()); 
                               return 0; 
                          } else {
                               fprintf(stderr, "CompletionThread: CreateIoCompletionPort: %d\n", hrc);
                          }

                          cic->deleteNode ( cicc->client_socket , cic );
                          cic->addNode ( cicc2 );

                     } else {
                          cout << endl << "Something Happened ... " << endl;
                     }
                }break;

                case 1:{
                     if ( ParsePacket ( cicc->client_socket , data ) ) {
                          cout << "Client " << cicc->client_socket << " connected." << endl;
                     } else {
                          cout << endl << "Something Happened ... " << endl;
                     }
                }break;

                default:{
                     cout << endl << "Didnt catch that operation ... " << cicc->operation << endl;
                }break;
           }

      } else if ( error == FALSE && &lpOverlapped == NULL )  {
           // no packet was dequed...
           fprintf(stderr, "[error == FALSE && &lpOverlapped == NULL] CompletionThread: GetQueuedCompletionStatus failed: %d [0x%x]\n", GetLastError(), &lpOverlapped->Internal);
      } else if ( error == FALSE && &lpOverlapped != NULL ) {
           if((DWORD)&lpOverlapped->Internal == 0x0) {     // a timeout...
           } else {
           fprintf(stderr, "[error == FALSE && &lpOverlapped != NULL] CompletionThread: GetQueuedCompletionStatus failed: %d [0x%x]\n", GetLastError(), &lpOverlapped->Internal);
           }
      }
 }

ExitThread(0);
return 0;
}

1 个答案:

答案 0 :(得分:1)

我不想再这样做,但我是对的,你必须使用WSARECV将套接字置于一个新模式(很像accepttex):我不知道这个,它在MSDN上不是很清楚,一个我正在寻找学习IOCP的消息来源,并没有谈论它。希望这有助于某人:/

WSABUF  wbuf; 
DWORD   bytes, flags;
wbuf.buf = cicc2->client_buff; 
wbuf.len = cicc2->client_len;
flags = 0;
int rr = WSARecv ( cicc2->client_socket , &wbuf , 1 , &bytes , &flags , &cicc2->ol , NULL );
    if (rr == FALSE) {
        if (WSAGetLastError() != WSA_IO_PENDING) {
            printf("PostRecv: WSARecv* failed: %d\n", WSAGetLastError());
            closesocket(cicc2->client_socket);
            cic->deleteNode ( cicc2->client_socket , cic );
        }
        fprintf(stderr, "PostRecv: WSARecv* failed: %d\n", GetLastError());
    }