Nenhum servidor OnAccept notifica quando faz o client Conecta uma segunda vez

9

Eu escrevi um aplicativo MFC C ++ onde o processo do meu cliente faz um% TCP MyCAsyncSocket::Connect para o processo do servidor. O processo do servidor responde com um MyCAsyncSocket::OnAccept que então Detach es o soquete como é prescrito, cria um thread que Attach es aquele soquete, que então lê os dados sendo enviados. O MSDN prescreve que m_hSocket seja definido como NULL após Detach .

Funciona bem, mas apenas uma vez. Na segunda vez em que o cliente tenta Connect para o mesmo endereço de soquete, nenhuma notificação OnAccept ocorre. Aqui está o código do servidor:

void MyCAsyncSocket::OnAccept( int nErrorCode )
{
  BOOL socketResult = FALSE;

  CAsyncSocket syncSocket;

  Accept( syncSocket );
  AsyncSelect( FD_READ | FD_CLOSE );

  SOCKET socket = syncSocket.Detach();
  m_hSocket = NULL; // prescribed by msdn

  ... // go attach the socket in a worker thread, read the socket and do work

  // try to re-establish listener.
  ...Create( // error: attempt 2: ASSERT(m_hSocket == INVALID_SOCKET)
    endPoint.portNumber, // ok: same as client port number
    SOCK_STREAM,
    FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
    endPoint.ipAddress // ok: same as client ip address
  );

  ...Listen(); // error: attempt 1: no error case, but still doesn't work


  CAsyncSocket::OnAccept( nErrorCode );
}

Tentativa 1: Em OnAccept após o Detach tentei seguir com um Listen , mas recebo este erro de escuta: “WSAENOTSOCK: O descritor não é um soquete”. Não tenho certeza do que isso significa.

Tentativa 2: tentei fazer um Create antes do acompanhamento Listen , mas isso causou uma declaração: ASSERT(m_hSocket == INVALID_SOCKET); , que é definido como:

/*
* This is used instead of -1, since the
* SOCKET type is unsigned.
*/
#define INVALID_SOCKET  (SOCKET)(~0)

No código do protótipo, eu simplesmente destruí o soquete do listener e recriou-o do zero, mas para o código de produção, isso não é aceitável, já que toda a idéia de Detach ing e re Attach ing é assegurar que o soquete capacidade de escuta do thread de soquete nunca é interrompida por mais de microssegundos.

Alguém sabe qual deve ser a semântica adequada para preparar o soquete para os Connect íons subseqüentes?

    
por rtischer8277 12.08.2016 в 17:46
fonte

1 resposta

2

Se eu estiver lendo isso corretamente, você chamará AsyncSelect (FD_READ | FD_CLOSE) no soquete listening - e eu acho que você realmente quer chamar isso no socket recém-aceito (syncSocket).

Eu esperaria que chamar AsyncSelect (FD_READ | FD_CLOSE) pudesse limpar a notificação FD_ACCEPT no socket de escuta - garantindo assim que nenhum OnAccept seja chamado quando conexões futuras forem feitas ao socket de escuta.

Além disso - quando você define m_hSocket = NULL acima, você está NULL-out o identificador do escutando soquete, não o soquete recém-aceito (syncSocket).

Além disso, se eu estiver lendo o MSDN corretamente ( link ), o Detach () método próprio NULLs o identificador relevante, e você não precisa fazer isso sozinho. [nem, eu espero, você pode - já que o m_hSocket deve ser um membro privado do syncSocket]

Espero que o seu código OnAccept seja mais parecido com:

void MyCAsyncSocket::OnAccept( int nErrorCode )
{
  BOOL socketResult = FALSE;

  CAsyncSocket syncSocket;

  Accept( syncSocket );

  SOCKET socket = syncSocket.Detach();

  ... // go attach the socket in a worker thread, which reads the socket and does work

}
    
por Kevin 20.08.2016 / 02:32
fonte