2012-07-19 84 views
1

編輯:我猜測問題是我必須將容器中的OVERLAPPED或WSAOVERLAPPED與我的完成端口相關聯。那是對的嗎?C++ CreateIoCompletionPort在新插座上

當有人連接到我的服務器時,我可以獲得IO完成。然後,我在新套接字上使用CreateIoCompletionPort,並使用原始的completionport。但是當他們向我發送數據時,它並沒有出現。儘管如果有人連接,它仍然會出現。我的問題是,爲什麼會發生這種情況?我也確保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; 
} 
+0

你打電話只能在被動監聽套接字'CreateIoCompletionPort',或在新接受的套接字呢?雖然我沒有使用完成端口的經驗,但通常您必須手動配置已接受的套接字,但它們不會從套接字「繼承」任何東西。 – 2012-07-19 09:38:33

+0

我只在新的套接字上調用它。我還分配了一個新的空間來創建一個新的套接字,並將接受的套接字複製到新的套接字中,並將completionport放置在那裏,沒有任何反應。 – User 2012-07-19 09:42:41

+0

你能否告訴我們相關的代碼?如果你向我們展示你所做的事情,幫助你將會簡單得多。 – 2012-07-19 10:03:25

回答

1

標識討厭再次做到這一點,但我是正確的,你必須使用的WSARecv到插座置於一個新的模式(很像的AcceptEx):我不知道這一點,它在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()); 
    }