Почему неблокирующая розетка подключается так медленно? - PullRequest
9 голосов
/ 18 июля 2011

, когда я выполняю 100 подключений неблокированных сокетов в 1 потоке, это очень медленно (количество подключений увеличивается один за другим), но если я выполняю блокирующее подключение сокетов в 100 параллельных потоках (по одному подключению на поток), это очень быстро (сделано немедленно)

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;

1 Ответ

5 голосов
/ 18 июля 2011

Удивительный вопрос :-). Вот почему я думаю, что это происходит. Стандарт гласит:

Если соединение не может быть установлено немедленно и O_NONBLOCK имеет значение установить для файлового дескриптора для сокета, connect () должен произойти установите errno на [EINPROGRESS]

Вопрос, конечно же, что означает "немедленно" . Я полагаю, что «немедленно» - это действительно небольшое время, которое позволяет SYN, SYN-ACK, ACK произойти. Если бы он вообще не ожидал, у него был бы нулевой шанс на успех.

Так в основном:

  • Клиент отправляет SYN
  • Ожидание (блоков) в течение небольшого промежутка времени («немедленно») в течение SYN-ACK.
  • Завершает соединение

При этом он успешно возвращается вместо EADDRINUSE.

Теперь, когда используются потоки, каждый поток делает это, так что никто не ждет. Все они просто connect(2), а переключение контекста позволяет всем делать это почти одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...