С++ CreateIoCompletionPort в новом сокете

РЕДАКТИРОВАТЬ: я предполагаю, что проблема в том, что мне нужно связать OVERLAPPED или WSAOVERLAPPED в контейнере с моим портом завершения. Это правильно?

Я могу получать завершения ввода-вывода, когда кто-то подключается к моему серверу. Затем я использую 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;
}

person User    schedule 19.07.2012    source источник
comment
Вы вызываете CreateIoCompletionPort только на сокете пассивного прослушивания или также на новых принятых сокетах? Хотя у меня нет опыта работы с портами завершения, обычно вы должны настраивать принятые сокеты вручную, они ничего не наследуют от сокета прослушивания.   -  person Some programmer dude    schedule 19.07.2012
comment
Я вызываю это только на новом сокете. Я также выделил новое пространство для создания совершенно нового сокета, скопировал принятый сокет в новый сокет и поместил туда порт завершения, ничего не происходит.   -  person User    schedule 19.07.2012
comment
Не могли бы вы показать нам соответствующий код? Помочь вам будет намного проще, если вы покажете нам, что вы делаете.   -  person Some programmer dude    schedule 19.07.2012
comment
@JoachimPileborg Хорошо, загружено.   -  person User    schedule 19.07.2012


Ответы (1)


Мне не хотелось бы делать это снова, но я был прав, вы должны перевести сокет в новый режим (очень похожий на acceptex) с помощью WSARECV: я этого не знал, и это не очень ясно в 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());
    }
person User    schedule 19.07.2012