Domanda

Sto cercando di codificare un piccolo test-server per le porte di completamento. Ma quando provo a chiamare AcceptEx ... ritorna sempre WSAEINVAL come il codice di errore del Winsock ... Io non davvero ottenere ciò che è stato il mio errore

http://codepad.org/NEXG3Ssh <- codice su tastiera codici

e

StartWinsock();
 cout << "Winsock initiated\n";
 //Get the number of processors
 DWORD ulProcessors = GetNumberOfProcessors();
 cout << "Number of Processors/Threads, that will be used: " << ulProcessors << endl;
 //Create an completion port
 hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, ulProcessors);
 if(hCompletionPort == NULL)
  ErrorAbort("Could not create completion port");
 cout << "Completion Port created\n";

 //Create threads
 CreateThreads(ulProcessors);
 cout << "Threads created\n";

 //Create socket
 AcceptorSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 addrinfo *final, hints;
 memset(&hints, 0, sizeof(hints));
 hints.ai_family = AF_INET;
 hints.ai_flags = AI_PASSIVE;
 if(getaddrinfo(NULL,"12345", &hints, &final))
  ErrorAbort("Could not retrieve address information");
 if(bind(AcceptorSock,final->ai_addr, final->ai_addrlen))
  ErrorAbort("Could not bind socket");
 freeaddrinfo(final);
 cout << "Acceptor socket created and bound\nStarting to listen on the acceptor socket\n";
 if(listen(AcceptorSock, 2))
  ErrorAbort("Can´t listen on the socket");

 //Add acceptor socket file handle to be observed by the completion port
 if(CreateIoCompletionPort((HANDLE)AcceptorSock, hCompletionPort, NEW_CONNECTION, 0) != hCompletionPort)
  ErrorAbort("A new completion port has been created instead of using the existing one");
 cout << "Acceptor socket associated with the completion port\n";

 ResumeThreads(2);
 char lpOutputBuf[1024];
 int outBufLen = 1024;
 DWORD dwBytes;
 OVERLAPPED over;
 SOCKET newSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);


 while(true)
 {
  memset(&over, 0, sizeof(over));
  if(AcceptEx(AcceptorSock, newSock, lpOutputBuf, outBufLen - ((sizeof(sockaddr_in) + 16) * 2), sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &dwBytes, &over) == FALSE)
  {
   int x = WSAGetLastError();
   if( x != WSA_IO_PENDING)
    ErrorAbort("Could not acceptex a new connection");
  }
 }
È stato utile?

Soluzione

problema Te nel codice è questo:

while(true)
{
  memset(&over, 0, sizeof(over));
  if(AcceptEx(AcceptorSock, newSock, lpOutputBuf, outBufLen - ((sizeof(sockaddr_in) + 16) * 2), sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &dwBytes, &over) == FALSE)
  {
    int x = WSAGetLastError();
    if( x != WSA_IO_PENDING)
    ErrorAbort("Could not acceptex a new connection");
  }
}

Il secondo parametro della funzione AcceptEx (in questo caso newSock) deve essere presa sconnesso e non legata, quindi quando una nuova connessione arriva il parametro newSock sarà un parametro non valido (perché ora è collegata), per evitare questo una nuova presa maniglia deve essere creato, ma il ciclo dovrà attendere che la nuova connessione arriva, per fare questo un WSAEVENT deve essere utilizzato. La prima la funzione WSAEventSelect deve essere utilizzata per associare l'evento FD_ACCEPT rete con l'WSAEVENT, questo mus essere fatto prima della creazione del AcceptThread:

g_ev = WSACreateEvent();
if (WSA_INVALID_EVENT == g_ev)
  ErrorAbort("Error occurred while WSACreateEvent()";
if (SOCKET_ERROR == WSAEventSelect(AcceptorSock, g_ev, FD_ACCEPT))
{
  WSACloseEvent(g_ev);
  ErrorAbort("Error occurred while WSAEventSelect().");
}

L'AcceptThread quindi chiamare la funzione AcceptEx e attendere una nuova connessione, quando arriva una nuova connessione il newSock viene aggiunto alla porta di completamento e viene creato un nuovo socket, questa discussione ha solo gli elementi necessari per accettare connessioni:

DWORD WINAPI AcceptThread(LPVOID lParam)
{
  SOCKET AcceptorSock = (SOCKET)lParam, new;
  SOCKET newSock; 
  OVERLAPPED over;    
  DWORD wr;

  memset(&over, 0, sizeof(over));
  do
  {
    newSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(AcceptEx(AcceptorSock, newSock, lpOutputBuf, outBufLen - ((sizeof(sockaddr_in) + 16) * 2), sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &dwBytes, &over) == FALSE)
    {
      int x = WSAGetLastError();
      if (x != ERROR_IO_PENDING)
      {
        cout << "Could not acceptex a new connection" << endl;
        return 1;
      }
      else
      {
        if (WSA_WAIT_TIMEOUT != (wr = WSAWaitForMultipleEvents(1,  &g_ev, FALSE, INFINITE, FALSE)))
        {
          WSAEnumNetworkEvents(AcceptorSock, g_ev, &WSAEvents);
          if ((WSAEvents.lNetworkEvents & FD_ACCEPT) &&  (0 == WSAEvents.iErrorCode[FD_ACCEPT_BIT]))
          {
            if (CreateIoCompletionPort(newSock, hCompletionPort, 0, 0) == NULL)
            {
              cout << "Error CreateIoCompletionPort" << endl;
              return 2;
            }
            WSAResetEvent(g_ev);
          }
        }
      }
    }
  }while(wr != WSA_WAIT_EVENT_0);
}

Se uno qualsiasi corpo ha bisogno di ulteriori informazioni questo link potrebbe essere utile: http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancedscalableapp6b.html http://www.codeproject.com/KB/IP/SimpleIOCPApp.aspx http://msdn.microsoft.com/en-us/magazine/cc302334.aspx

Altri suggerimenti

SOCKET newSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

dovrebbe usare WSASocket piuttosto che socket e si dovrebbe passare il flag WSA_FLAG_OVERLAPPED durante la creazione del socket.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top