Por que o soquete não-bloqueante é conectado tão lento?

9

quando faço 100 conexões de soquete não-bloco em 1 thread, é muito lento (o número de conexão aumentou um por um), mas se eu fizer uma conexão de soquete de bloqueio em 100 threads paralelos (uma conexão por thread), é muito rápido (seja feito imediatamente)

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fcntl(sock, F_SETFL,O_NONBLOCK)!=0)
{
 perror("fcntl nonblock");
 return -1;
}

if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,&reuseAddr, sizeof(reuseAddr))!=0)
{
  perror("reuse addr");
  return -1;
}

sAddr.sin_addr.s_addr = inet_addr(SRV_ADDR);
sAddr.sin_port = htons(1972);

if ((n=connect(sock, (const struct sockaddr *) &sAddr, sizeof(sAddr))) < 0) 
{
  if (errno !=EINPROGRESS) {
      perror("client connect error");
      return -1;
  }     
}
else if (n>=0)
{
  printf("#%d connected\n",sock);
}

return sock;
    
por jon 18.07.2011 в 10:44
fonte

1 resposta

5

Pergunta incrível :-). Aqui está porque eu acho que isso está acontecendo. O padrão diz isso:

  

Se a conexão não puder ser estabelecida imediatamente e O_NONBLOCK for   definido para o descritor de arquivo para o soquete, connect () deve falhar e   defina errno como [EINPROGRESS]

A questão é claro o que significa "imediatamente" . Eu acredito que "imediatamente" é na verdade um pouco de tempo que permite que o SYN , SYN-ACK , ACK aconteça. Se não esperasse nada, teria 0 chance de ter sucesso.

Então basicamente:

  • O cliente envia um SYN
  • Espera (blocos) por um pequeno período de tempo ("imediatamente") por SYN-ACK .
  • Conclui a conexão

Ao fazer isso, ele retorna com sucesso, em vez de EADDRINUSE .

Agora, ao usar threads, cada thread faz isso para que ninguém aguarde. Todos eles apenas connect(2) e mudança de contexto permitem que todos façam isso quase simultaneamente.

    
por cnicutar 18.07.2011 / 11:05
fonte