Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is non-blocking socket connect so slow?

Tags:

c

sockets

when I do 100 non-block socket connection in 1 thread,it is very slow(the number of connection increased one by one),but if I do a blocking socket connection in 100 parallel threads(one connect per thread), it is very fast(get done immediately )

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;
like image 555
jon Avatar asked Jul 18 '11 08:07

jon


People also ask

How can you tell if a socket is blocking or non-blocking?

From MSDN, the return value of connect(): On a blocking socket, the return value indicates success or failure of the connection attempt. With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR , and WSAGetLastError() will return WSAEWOULDBLOCK.

Is TCP connect blocking?

connect() on a TCP socket is a blocking operation unless the socket descriptor is put into non-blocking mode. A successful TCP handshake will be queued to the server application, and can be accept()'ed any time later.

What are non-blocking sockets?

In blocking socket mode, a system call event halts the execution until an appropriate reply has been received. In non-blocking sockets, it continues to execute even if the system call has been invoked and deals with its reply appropriately later.


1 Answers

Awesome question :-). Here's why I think this is happening. The standard says this:

If the connection cannot be established immediately and O_NONBLOCK is set for the file descriptor for the socket, connect() shall fail and set errno to [EINPROGRESS]

The question of course is what "immediately" means. I believe that "immediately" is actually some small time that allows the SYN, SYN-ACK, ACK to happen. If it didn't wait at all, it would have 0-chance of actually succeeding.

So basically:

  • The client sends a SYN
  • Waits (blocks) for a small period of time ("immediately") for a SYN-ACK.
  • Completes the connection

In doing so it returns successfully instead of EADDRINUSE.

Now, when using threads, each thread does this so nobody waits. They all just connect(2) and context switching allows everybody to do it almost simultaneously.

like image 68
cnicutar Avatar answered Oct 22 '22 18:10

cnicutar