TCP connect in Non Blocking Mode - TCP-IP

This is a discussion on TCP connect in Non Blocking Mode - TCP-IP ; Hi, I have searched high and low and am unable to find a problem similar to mine on the internet, so I though of asking here. The problem I am having is similar to this thread: http://groups.google.com/group/comp....83eefd264d2597 in that I ...

+ Reply to Thread
Results 1 to 6 of 6

Thread: TCP connect in Non Blocking Mode

  1. TCP connect in Non Blocking Mode

    Hi,

    I have searched high and low and am unable to find a problem similar
    to mine on the internet, so I though of asking here. The problem I am
    having is similar to this thread:

    http://groups.google.com/group/comp....83eefd264d2597

    in that I am creating a nonblocking client socket and using the
    select() function to determine if a connection has been made (by
    setting both fd_set *writefds and fd_set *exceptfds). The problem
    arises where in the case that there is no service listening at the
    remote end a RST packet is returned after a SYN request for a
    connection.

    In windows everything works perfectly by setting fd_set *exceptfds.
    The select() function exits as soon as an RSTpacket arrives and
    reports connection refused as I expected.

    In linux however no matter what I do, when a RST packet arrives
    nothing seems to happen and select() remains blocking until the
    timeout expires. I have tried compiling this on both Debian 3.1 and
    RedHat 7.2, in both cases the outcome is identical.

    Does anyone have any idea how linux handles RST packets in a non
    blocking connect? as I assume if a "Connection Refused" situation
    arises there is no point sticking around for a retry.

    I have attached my full connect function below, if someone with a bit
    more experience than me could be kind enough to point me in the right
    direction.

    thanks

    Rekkie



    void Socket::Port::connect_withTimeout(const Socket::Address& inPeer,
    long msTimeout)
    {
    int res;
    int on = 1;
    fd_set myset;
    struct timeval lTime;
    int valopt;
    socklen_t lon;

    std:stringstream lMessage;
    lMessage << "unable to connect to server: \"" <<
    inPeer.getHostName();
    lMessage << "\" at port:" << inPeer.getPortNumber() << "\n";

    if(mDescriptor == INVALID_SOCKET) throw Exception(eBadDescriptor,
    "Port::connect() invalid socket");
    struct sockaddr_in lSock;
    lSock.sin_family = AF_INET;
    lSock.sin_port = htons(inPeer.getPortNumber());
    lSock.sin_addr.s_addr = inet_addr(inPeer.getIPAddress().c_str());
    memset(&lSock.sin_zero, 0, 8);

    /************************************************** ***********/
    /* Set socket to be non-blocking. */
    /************************************************** ***********/
    #ifdef WIN32
    // Set non-blocking - WINDOWS
    //-------------------------
    // Set the socket I/O mode: In this case FIONBIO
    // enables or disables the blocking mode for the
    // socket based on the numerical value of iMode.
    // If iMode = 0, blocking is enabled;
    // If iMode != 0, non-blocking mode is enabled.

    u_long iMode = 1;

    res = ioctlsocket(mDescriptor, FIONBIO, &iMode);
    if (res != 0)
    {
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() ioctl() failed(" << ErrNo
    << ")";
    close();
    throw Exception(lCode, lMessage.str());
    }

    #else
    long arg;

    // Set non-blocking - UNIX
    if( (arg = fcntl(mDescriptor, F_GETFL, NULL)) < 0) {
    //fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n",
    strerror(errno));
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error fcntl(..., F_GETFL)
    (" << ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    arg |= O_NONBLOCK;
    if( fcntl(mDescriptor, F_SETFL, arg) < 0) {
    //fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n",
    strerror(errno));
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error fcntl(..., F_SETFL)
    (" << ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    #endif

    // Trying to connect with timeout
    res = ::connect(mDescriptor, (struct sockaddr*) &lSock,
    sizeof(lSock));
    if (res < 0)
    {
    //
    #ifdef WIN32 //WSAEWOULDBLOCK is normal on non blocking socket in
    windows
    if((ErrNo == WSAEWOULDBLOCK) || ((ErrNo == EINPROGRESS)))
    #else
    if (ErrNo == EINPROGRESS) //errno
    #endif
    {
    //fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
    do {
    lTime.tv_sec = (long) (msTimeout/1000);
    lTime.tv_usec = (long) (((msTimeout/1000)-
    lTime.tv_sec)*1000000);
    FD_ZERO(&myset);
    FD_SET(mDescriptor, &myset);
    res = select(mDescriptor+1, NULL, &myset, &myset /*NULL*/,
    &lTime);
    if (res < 0 && errno != EINTR) {
    //fprintf(stderr, "Error connecting %d - %s\n", errno,
    strerror(errno));
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error connecting (" <<
    ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    else if (res > 0)
    {
    // Socket selected for write
    lon = sizeof(int);
    if (getsockopt(mDescriptor, SOL_SOCKET, SO_ERROR, /*(void*)*/
    (char*)(&valopt), &lon) < 0)
    {
    //fprintf(stderr, "Error in getsockopt() %d - %s\n", errno,
    strerror(errno));
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error in getsockopt()
    (" << ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    // Check the value returned...
    if (valopt)
    {
    //fprintf(stderr, "Error in delayed connection() %d - %s\n",
    valopt, strerror(valopt));
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error in delayed
    connection() (" << ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    break;
    }
    else
    {
    //fprintf(stderr, "Timeout in select() - Cancelling!\n");
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Timeout in select() -
    Cancelling!";
    throw Exception(lCode, lMessage.str());
    }
    } while (1);
    }
    else
    {
    //fprintf(stderr, "Error connecting %d - %s\n", errno,
    strerror(errno));
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error connecting (" <<
    ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    }

    #ifdef WIN32
    iMode = 0;
    res = ioctlsocket(mDescriptor, FIONBIO, &iMode);
    if (res != 0)
    {
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() ioctl() failed(" << ErrNo
    << ")";
    close();
    throw Exception(lCode, lMessage.str());
    }
    #else
    // Set to blocking mode again - UNIX
    if( (arg = fcntl(mDescriptor, F_GETFL, NULL)) < 0)
    {
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error2 fcntl(..., F_GETFL)
    (" << ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    arg &= (~O_NONBLOCK);
    if( fcntl(mDescriptor, F_SETFL, arg) < 0)
    {
    int lCode = ErrNo;
    lMessage << "Port::connect_withTimeout() Error2 fcntl(..., F_SETFL)
    (" << ErrNo << ")";
    throw Exception(lCode, lMessage.str());
    }
    #endif
    /*if(::connect(mDescriptor, (struct sockaddr*) &lSock,
    sizeof(lSock)) != 0) {
    int lCode = ErrNo;
    std:stringstream lMessage;
    lMessage << "Port::connect() unable to connect to server: \"" <<
    inPeer.getHostName();
    lMessage << "\" at port:" << inPeer.getPortNumber();
    throw Exception(lCode, lMessage.str());
    }*/

    }

  2. Re: TCP connect in Non Blocking Mode

    Okay, I think I have figured it out, with a bit of help from several
    posts on the topic of RST packets getting ignored. I will answer my
    own question for the benefit of anyone else that encounters a similar
    problem.

    My problem seems to lie in the fact that I am running linux in a
    virtual machine, namely VMWare Workstation Version 5.5.4 build-44386.
    I am using virtual networking based on NAT, and for some reason the
    RST packets that get returned have their sequence number that does not
    correspond to SYN packet sent. This can be seen in the tcpdump
    below:

    10:42:27.350443 IP 192.168.168.200.32795 > 192.168.1.137.2530: S
    321814608:321814608(0) win 5840 0,nop,wscale 0>
    10:42:28.388339 IP 192.168.1.137.2530 > 192.168.168.200.32795: R
    366283094:366283094(0) win 64240
    10:42:30.348210 IP 192.168.168.200.32795 > 192.168.1.137.2530: S
    321814608:321814608(0) win 5840 0,nop,wscale 0>
    10:42:31.259639 IP 192.168.1.137.2530 > 192.168.168.200.32795: R
    1129414361:1129414361(0) win 64240

    Anyone know if this is a VMWare quirk/bug or if this happens normally
    across NAT interfaces. If this is normal how does one go about solving
    this?

    thanks

    Rekkie

  3. Re: TCP connect in Non Blocking Mode

    On Jul 24, 2:04*pm, Reks wrote:
    > Okay, I think I have figured it out, with a bit of help from several
    > posts on the topic of RST packets getting ignored. I will answer my
    > own question for the benefit of anyone else that encounters a similar
    > problem.
    >
    > My problem seems to lie in the fact that I am running linux in a
    > virtual machine, namely VMWare Workstation Version 5.5.4 build-44386.
    > I am using virtual networking based on NAT, and for some reason the
    > RST packets that get returned have their sequence number that does not
    > correspond to SYN packet sent. This can be seen in the tcpdump
    > below:
    >
    > 10:42:27.350443 IP 192.168.168.200.32795 > 192.168.1.137.2530: S
    > 321814608:321814608(0) win 5840 > 0,nop,wscale 0>
    > 10:42:28.388339 IP 192.168.1.137.2530 > 192.168.168.200.32795: R
    > 366283094:366283094(0) win 64240
    > 10:42:30.348210 IP 192.168.168.200.32795 > 192.168.1.137.2530: S
    > 321814608:321814608(0) win 5840 > 0,nop,wscale 0>
    > 10:42:31.259639 IP 192.168.1.137.2530 > 192.168.168.200.32795: R
    > 1129414361:1129414361(0) win 64240
    >
    > Anyone know if this is a VMWare quirk/bug or if this happens normally
    > across NAT interfaces. If this is normal how does one go about solving
    > this?
    >
    > thanks
    >
    > Rekkie


    Hi ,

    Could you please brife me on, blocking and non-blocking mode in tcp/
    ip.,

    Thanks,
    Manj

  4. Re: TCP connect in Non Blocking Mode

    On Thu, 24 Jul 2008 02:04:20 -0700, Reks wrote:

    > Anyone know if this is a VMWare quirk/bug or if this happens normally
    > across NAT interfaces. If this is normal how does one go about solving
    > this?


    It's absolutely not normal for NAT and I've never seen this behavior with
    VMWare. If VMWare did this, it would get fixed in a hurry I suppose.

    Are you sure the sequence number for the RST is meaningful? Maybe looking
    deeper with Wireshark, you'll find you're not seeing what you think you
    are seeing. But maybe you are, i don't know.

    HTH,
    M4

  5. Re: TCP connect in Non Blocking Mode

    > It's absolutely not normal for NAT and I've never seen this behavior with
    > VMWare. If VMWare did this, it would get fixed in a hurry I suppose.



    Yes I don't think it has much to do with NAT, but definitely linux
    drops the packets due to the sequence numbers being out of sync. If
    the address called is not one of the vmware interfaces ie iif I call
    127.0.0.1 the packets return with the right sequence number and get
    processed. Also outside of my virtual machine the program works
    correctly, so all I can assume is that it is a vmware bug.

    Rekkie




  6. Re: TCP connect in Non Blocking Mode

    > Hi ,
    >
    > *Could you please brife me on, blocking and non-blocking mode in tcp/
    > ip.,
    >
    > Thanks,
    > Manj



    Hi Manj,

    if you do a google search for blocking/non blocking sockets, you will
    find a host of information regarding blocking/nonblocking which will
    be both more complete and clearer than I would be able to write. If
    you still need some info let me know...

    Rekkie

+ Reply to Thread