1

編集:問題は、コンテナー内の 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;
}
4

1 に答える 1

1

私はこれをもう一度やりたくないのですが、私は正しかったです。WSARECV を使用してソケットを新しいモード (acceptex のように) に配置する必要があります: 私はこれを知りませんでした。私は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());
    }
于 2012-07-19T11:30:09.870 に答える