Looping connect call for a non blocking socket

will there be any unexpected results on looping connect call for a non blocking socket to determine the connection based on error code. I am getting connection unsuccessful intermittently and so wondering whether is the timeout 500 millisec not sufficient or looping connect cause any unexpected.

//sample piece of code that I used

int type,x, MaxTries=0;
type = SOCK_STREAM;
x = fcntl(s,F_GETFL, 0);
fcntl(s,F_SETFL, x | O_NONBLOCK);
if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
{
  while( (errno == EALREADY && MaxTries < 5) || (errno == EINPROGRESS && MaxTries < 5) )
                {
                        poll(NULL,0,100); //100 millisec sleep for 5 retries max.
                        connect(s, (struct sockaddr *)&sin, sizeof(sin));
                        MaxTries = MaxTries + 1;
                }
                if(errno == EISCONN)
                      printf("Connected");
                else
                      printf("Not Connected - %d",errno);
}

I know the Otherway is using SELECT. This would be better solution than looping but I doubt any significant difference in intermittent connections.

x = fcntl(s,F_GETFL, 0);
   fcntl(s,F_SETFL, x | O_NONBLOCK);

   FD_ZERO(&writeFDs);
   FD_SET(s, &writeFDs);

   timeout1.tv_sec = 0;
   timeout1.tv_usec = 500000;
   
   connect(s, (struct sockaddr *)&sin, sizeof(sin));
   if(select (maxFDs, (fd_set *)NULL, &writeFDs, (fd_set *)NULL, (struct timeval *)(&timeout1))  > 0 )   
        printf("Connected");
    else
       printf("Not Connected -%d", errno);

Correct approach is after calling connect() to check if errno is set to EINPROGRESS and if so use select() to see when socket can be written to, also its best not to loop 5 times but set a single timeout since your select() will fire up when socket would change state (in relation to connect()) right away and you re just wasting CPU cycles. Keep in mind that kernel has internal timeout maximum set for TCP handshakes that is somewhere 1-2mins after that connect() should return ETIMEDOUT no matter what you do and only then you would need to have to implement a loop.

Edit:
If your connect() fails at first run then your problem is not in non-blocking sockets, but on receiving end or somewhere in between or maybe you set up 'struct sockaddr sin' incorrectly.

I agree to use select but I want to correct that I don't loop 5 times wasting CPU cycle everytime. Worst case is 5 times. If the errno is EALREADY or EINPROGRESS I retry connect other wise I see for EISCONN.

I am believing this doesn't do anything with intermittent connections( Connection couldn't acquire in 500 milliseconds indicating errno - already inprogress) though is SELECT or looping connect. I am hoping 500 milli seconds not sufficient some times.

Do we have to keep the socket open till kernal level timeout occurs? We can also close the socket after custom timeout specified by using select?

The code as written will not work as you expect if the initial connect() call fails with EALREADY or EINPROGRESS.

You need to reset errno to zero before each connect call.

Successful system calls will not change the value of errno.

Thank You. I went for this looping logic because socket by default is writable. Rebooting the remote machine creating EPIPE and FD_ISSET(s, &writeFDs) returning success.

Do I have to do connect again to see the real state of the socket after FD_ISSET?

rc = select (maxFDs, (fd_set *)NULL, &writeFDs, (fd_set *)NULL, (struct timeval *)(&timeout1));

if(rc > 0 && FD_ISSET(s, &writeFDs))
{
    printf("Connection Success\n");
    write(s, "service", 7);
}

Yes you have to connect again to bind socket to a remote port for further communication, in other words connect must return 0 once for the socket.

So connect, select and again connect based on the return codes and errno indications achieve smooth non blocking connection but I am still thinking of looping connect call and I verified the truss to see the return code of connect when I loop -

First remote connect said - EINPROGRESS as expected.
Next try indicated - EISCONN. Indicating already connected.
Even if not then would have indicated EALREADY. Having 100 milli secods each time before trying to connect, there should not be any issue except that the last retry may indicate connect = 0 and will not update errno (The only chance of failure in the loop after 400 milli seconds, mostly in bad network cases). Other case If connect returned 0 will not update errno but the next try to same connected socket would indicate error - EISCONN, correct?

connect(4, 0x080453E0, 16, SOV_DEFAULT) Err#150 EINPROGRESS
pollsys(0x00000000, 0, 0x08045330, 0x00000000) = 0
connect(4, 0x080453E0, 16, SOV_DEFAULT) Err#133 EISCONN

Because you are always sleeping for a fixed time on every case, on a good network you will always have a time loss of the initial sleep even if the socket is ready for use already. It will work, but I think thats bad design. You should always do select and check connect return value before doing a possibly wasteful sleep.