2012-07-19 31 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()); 
    }