1

EDIT: I am guessing the problem is I have to associate the OVERLAPPED or WSAOVERLAPPED in the container with my completion port. Is that correct?

I can get IO completions when someone connects to my server. I then use CreateIoCompletionPort on the new socket, with the completionport that original was used. But when they send me data, it does not get set off. Although, it still gets set off if someone else connects. My question is, why would this happen? I also make sure CreateIoCompletionPort returns the same handle as was the original. What gives?

EDIT:

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;
}
User
  • 659
  • 2
  • 12
  • 29
  • Do you call `CreateIoCompletionPort` only on the passive listening socket, or on the new accepted sockets as well? While I'm not experienced with completion ports, in general you have to configure accepted sockets manually, they don't "inherit" anything from the listening socket. – Some programmer dude Jul 19 '12 at 09:38
  • I call it on the new socket only. I also allocated new space to make a whole new socket, and copied the accepted socket to the new socket, and placed the completionport on there, nothing happens. – User Jul 19 '12 at 09:42
  • Could you perhaps show us the relevant code? It will be much simpler to help you if you show us what you do. – Some programmer dude Jul 19 '12 at 10:03
  • @JoachimPileborg Alright, uploaded. – User Jul 19 '12 at 10:14

1 Answers1

1

Id hate to do this again, but I was correct, you have to place the socket into a new mode (much like acceptex) using WSARECV: I did not know this, and its not very clear on the MSDN, and one of the sources I was looking at to learn IOCP, doesn't talk about it. Hopefully this helps someone :/

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());
    }
User
  • 659
  • 2
  • 12
  • 29