TCP connect in Non Blocking Mode - TCP-IP

This is a discussion on TCP connect in Non Blocking Mode - TCP-IP ; Hi, My client application tries to connect to the server in the following manner: ...../ err = connect(sd, (struct sockaddr*) &sa, sizeof(sa)); if(err == -1) { if(errno == EINPROGRESS) { struct timeval l_connect_timeout; int l_fds; l_connect_timeout.tv_usec=0; l_connect_timeout.tv_sec=30; //30 seconds. while(1) ...

+ Reply to Thread
Results 1 to 8 of 8

Thread: TCP connect in Non Blocking Mode

  1. TCP connect in Non Blocking Mode

    Hi,

    My client application tries to connect to the server in the following
    manner:

    ...../
    err = connect(sd, (struct sockaddr*) &sa, sizeof(sa));

    if(err == -1)
    {
    if(errno == EINPROGRESS)
    {
    struct timeval l_connect_timeout;
    int l_fds;
    l_connect_timeout.tv_usec=0;
    l_connect_timeout.tv_sec=30; //30 seconds.

    while(1)
    {
    l_fds=select(sd+1, NULL,&filedes_set,NULL,
    &l_connect_timeout);
    if(l_fds == 0) //timed out
    return 0;
    else if(l_fds < 0) //select failed
    return 0;
    else
    {
    int l_sock_optval=-1;
    int l_sock_optval_len=sizeof(l_sock_optval);
    if(getsockopt(sd, SOL_SOCKET, SO_ERROR, (int*)&l_sock_optval,
    (socklen_t*)&l_sock_optval_len) !=0)
    {

    return 0;
    }

    if(l_sock_optval == 0)
    {
    //connected to server
    break;
    }
    }


    }

    }

    This works fine. The issue that I face is when the server refuses
    connection by sending RST for the SYN from client. The select waits
    for 30 seconds and later returns timing out. RST though is sent
    immediately by the server. The client application need to capture the
    RST as soon as it arrives. How do we achieve that. Why does not the
    select return immediately when the RST arrives at client?

    Thanks,
    Prabhu. S

  2. Re: TCP connect in Non Blocking Mode

    In article <0f9b8a7c-083a-4573-ae5a-b7dc57c51b8b@m1g2000pre.googlegroups.com>, yesprabhu@gmail.com (Prabhu) writes:
    | Hi,
    |
    | My client application tries to connect to the server in the following
    | manner:
    |
    | ..../
    | err = connect(sd, (struct sockaddr*) &sa, sizeof(sa));
    |
    | if(err == -1)
    | {
    | if(errno == EINPROGRESS)
    | {
    | struct timeval l_connect_timeout;
    | int l_fds;
    | l_connect_timeout.tv_usec=0;
    | l_connect_timeout.tv_sec=30; //30 seconds.
    |
    | while(1)
    | {
    | l_fds=select(sd+1, NULL,&filedes_set,NULL,
    | &l_connect_timeout);
    | if(l_fds == 0) //timed out
    | return 0;
    | else if(l_fds < 0) //select failed
    | return 0;
    | else
    | {
    | int l_sock_optval=-1;
    | int l_sock_optval_len=sizeof(l_sock_optval);
    | if(getsockopt(sd, SOL_SOCKET, SO_ERROR, (int*)&l_sock_optval,
    | (socklen_t*)&l_sock_optval_len) !=0)
    | {
    |
    | return 0;
    | }
    |
    | if(l_sock_optval == 0)
    | {
    | //connected to server
    | break;
    | }
    | }
    |
    |
    | }
    |
    | }
    |
    | This works fine. The issue that I face is when the server refuses
    | connection by sending RST for the SYN from client. The select waits
    | for 30 seconds and later returns timing out. RST though is sent
    | immediately by the server. The client application need to capture the
    | RST as soon as it arrives. How do we achieve that. Why does not the
    | select return immediately when the RST arrives at client?

    Are you sure it doesn't? You have a loop around the select(). When
    select() indicates that the socket is writable you retrieve and clear
    the socket's stored error with getsockopt(...SO_ERROR...). Then if the
    error is not zero you loop back to the select(). Since the socket's
    stored error is no longer set (and obviously there is no connection) the
    socket is not considered writable by select(). Thus it will block until
    your timeout expires. This will happen for any error; not just a refused
    connection. Does this code really work fine for any case but success?

    Dan Lanciani
    ddl@danlan.*com

  3. Re: TCP connect in Non Blocking Mode

    On Apr 22, 12:33 pm, ddl@danlan.*com (Dan Lanciani) wrote:
    > In article <0f9b8a7c-083a-4573-ae5a-b7dc57c51...@m1g2000pre.googlegroups.com>, yespra...@gmail.com (Prabhu) writes:
    > | Hi,
    > |
    > | My client application tries to connect to the server in the following
    > | manner:
    > |
    > | ..../
    > | err = connect(sd, (struct sockaddr*) &sa, sizeof(sa));
    > |
    > | if(err == -1)
    > | {
    > | if(errno == EINPROGRESS)
    > | {
    > | struct timeval l_connect_timeout;
    > | int l_fds;
    > | l_connect_timeout.tv_usec=0;
    > | l_connect_timeout.tv_sec=30; //30 seconds.
    > |
    > | while(1)
    > | {
    > | l_fds=select(sd+1, NULL,&filedes_set,NULL,
    > | &l_connect_timeout);
    > | if(l_fds == 0) //timed out
    > | return 0;
    > | else if(l_fds < 0) //select failed
    > | return 0;
    > | else
    > | {
    > | int l_sock_optval=-1;
    > | int l_sock_optval_len=sizeof(l_sock_optval);
    > | if(getsockopt(sd, SOL_SOCKET, SO_ERROR, (int*)&l_sock_optval,
    > | (socklen_t*)&l_sock_optval_len) !=0)
    > | {
    > |
    > | return 0;
    > | }
    > |
    > | if(l_sock_optval == 0)
    > | {
    > | //connected to server
    > | break;
    > | }
    > | }
    > |
    > |
    > | }
    > |
    > | }
    > |
    > | This works fine. The issue that I face is when the server refuses
    > | connection by sending RST for the SYN from client. The select waits
    > | for 30 seconds and later returns timing out. RST though is sent
    > | immediately by the server. The client application need to capture the
    > | RST as soon as it arrives. How do we achieve that. Why does not the
    > | select return immediately when the RST arrives at client?
    >
    > Are you sure it doesn't? You have a loop around the select(). When
    > select() indicates that the socket is writable you retrieve and clear
    > the socket's stored error with getsockopt(...SO_ERROR...). Then if the
    > error is not zero you loop back to the select(). Since the socket's
    > stored error is no longer set (and obviously there is no connection) the
    > socket is not considered writable by select(). Thus it will block until
    > your timeout expires. This will happen for any error; not just a refused
    > connection. Does this code really work fine for any case but success?
    >
    > Dan Lanciani
    > ddl@danlan.*com


    Dan,

    Yes. It seems like the code seems like to work for only successful
    scenarios. But how can the applications handle RSTs immediately. I
    tried the following way to do the connection:

    err = connect(sd, (struct sockaddr*) &sa, sizeof(sa));

    if(err == -1)
    {
    if(errno == EINPROGRESS)
    {
    char lbuf[] = {0x00};

    while(1)
    {
    int temp=0;


    if(send(sd,lbuf,0,0 ) == -1) //send zero byte

    {
    temp = errno;
    if(temp== ECONNREFUSED)
    {
    //connection refused!

    return 0;
    }
    else if(temp== EAGAIN )
    {
    //try again
    }
    else if(temp == EHOSTUNREACH)
    {
    //No route to AG address specified
    return 0;
    }
    else if(temp==ETIMEDOUT)
    {
    //Connection timed out
    return 0;
    }
    else if(temp == ECONNRESET)
    {
    //Connection reset by peer
    return 0;
    }
    else
    return 0;

    }
    else
    break; //connected to server.
    }
    }
    }

    This method was successful. It also helped in catching RSTs
    immediately. But the problem with this method is my application
    creates hundreds of threads(>500). Each thread would try connecting to
    the server. Under stress the application reports SIGPIPEs , possibly
    because of 'send' in the connection process. But I observe connections
    are successful. Also I see a marked increased in the CPU utilization
    by the application with this method.

    Thanks,
    Prabhu. S

  4. Re: TCP connect in Non Blocking Mode

    On Apr 22, 2:21 am, Prabhu wrote:

    > Dan,
    >
    > Yes. It seems like the code seems like to work for only successful
    > scenarios. But how can the applications handle RSTs immediately. I
    > tried the following way to do the connection:


    Dan already answered that question. The code you demonstrated has a
    bug in it, so fix the bug. Then see if you still have the problem with
    RSTs.

    [snip]
    > This method was successful. It also helped in catching RSTs
    > immediately. But the problem with this method is my application
    > creates hundreds of threads(>500). Each thread would try connecting to
    > the server. Under stress the application reports SIGPIPEs , possibly
    > because of 'send' in the connection process. But I observe connections
    > are successful. Also I see a marked increased in the CPU utilization
    > by the application with this method.


    That's awful, don't do that. Fix the bug Dan found.

    DS

  5. Re: TCP connect in Non Blocking Mode

    On Apr 23, 2:27 am, David Schwartz wrote:
    > On Apr 22, 2:21 am, Prabhu wrote:
    >
    > > Dan,

    >
    > > Yes. It seems like the code seems like to work for only successful
    > > scenarios. But how can the applications handle RSTs immediately. I
    > > tried the following way to do the connection:

    >
    > Dan already answered that question. The code you demonstrated has a
    > bug in it, so fix the bug. Then see if you still have the problem with
    > RSTs.
    >
    > [snip]
    >
    > > This method was successful. It also helped in catching RSTs
    > > immediately. But the problem with this method is my application
    > > creates hundreds of threads(>500). Each thread would try connecting to
    > > the server. Under stress the application reports SIGPIPEs , possibly
    > > because of 'send' in the connection process. But I observe connections
    > > are successful. Also I see a marked increased in the CPU utilization
    > > by the application with this method.

    >
    > That's awful, don't do that. Fix the bug Dan found.
    >
    > DS


    I did the following to fix. It is working now.:

    if(getsockopt(sd, SOL_SOCKET, SO_ERROR, (int*)&l_sock_optval,
    (socklen_t*)&l_sock_optval_len) !=0)
    {
    return 0;
    }

    if(l_sock_optval == 0)
    {
    //connection sucess
    break;
    }
    else if(l_sock_optval == ECONNREFUSED)
    {
    //connection refused.
    return 0;
    }

    This is appropriate, isn't?. Please comment.

    Thanks,
    Prabhu. S

  6. Re: TCP connect in Non Blocking Mode

    In article <037a4d7a-53aa-4660-ae1d-22773be15a74@j22g2000hsf.googlegroups.com>, yesprabhu@gmail.com (Prabhu) writes:

    | I did the following to fix. It is working now.:
    |
    | if(getsockopt(sd, SOL_SOCKET, SO_ERROR, (int*)&l_sock_optval,
    | (socklen_t*)&l_sock_optval_len) !=0)
    | {
    | return 0;
    | }
    |
    | if(l_sock_optval == 0)
    | {
    | //connection sucess
    | break;
    | }
    | else if(l_sock_optval == ECONNREFUSED)
    | {
    | //connection refused.
    | return 0;
    | }
    |
    | This is appropriate, isn't?. Please comment.

    It doesn't deal with errors other than ECONNREFUSED. Or at least, it doesn't
    deal with them in a way I would consider useful. I assume this code is still
    within a loop. What are you trying to accomplish with that loop? You can't
    compensate for a select() that falses positive; the select()/SO_ERROR method
    of handling asynchronous connect()s implicitly depends on a select() that
    does not false in this context. If you are indeed worried about false
    positives you need to use a select()/connect() approach. If not then you
    should eliminate the loop.

    Dan Lanciani
    ddl@danlan.*com

  7. Re: TCP connect in Non Blocking Mode

    Prabhu wrote:
    > This works fine.


    It shouldn't. You're supposed to repeat the connect() call once the
    socket FD selects as writable, and then test the result of *that*.

  8. Re: TCP connect in Non Blocking Mode

    On Apr 25, 12:55 am, EJP wrote:
    > Prabhu wrote:
    > > This works fine.

    >
    > It shouldn't. You're supposed to repeat the connect() call once the
    > socket FD selects as writable, and then test the result of *that*.


    Or you can issue a non-blocking read or you can use
    getsockopt(SO_ERROR). But you are quite correct that a zero-byte
    operation is undefined and should definitely not be used.

    DS

+ Reply to Thread