nitred

CC3200 : How to reduce TCP Connect Timeout when there's no internet?

6 posts in this topic

Hello,

 

In the case there's no internet and I'm trying to connect to a TCP Server on the CC3200 using the following statement

tcp.connect(remote_ip, remote_port)    // WiFiClient.connect

My program hangs for 30 SECONDS on the above statement.

 

Is there a library file where I can reduce this timeout to something more reasonable like 5 seconds?

 

Thanks!

Share this post


Link to post
Share on other sites

I think technically speaking there is a sl_SetSockOpt() parameter that might change this:

#define SL_SO_RCVTIMEO         (20)  /* Enable receive timeout */
 
But I haven't tinkered with it and Energia certainly doesn't supply any way to modify it easily.

Share this post


Link to post
Share on other sites

i am also facing this issue....

Has any one found out the solution??

Share this post


Link to post
Share on other sites

This is currently not supported as posted in this thread: https://e2e.ti.com/support/wireless_connectivity/simplelink_wifi_cc31xx_cc32xx/f/968/p/465212/1670436#1670436

 

What you can do is to change WiFiClient.ccp's connect function to make the connect non-blocking with sl_SetSockOpt(socketHandle, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &enableOption, sizeof(enableOption)); sl_Connect will then return immediately regardless of successful connection. Then change the code after connect to something like posted here: https://e2e.ti.com/support/wireless_connectivity/simplelink_wifi_cc31xx_cc32xx/f/968/t/473029

 

It might be a good idea for the WiFi library to support a connect() with optional timeout. Unfortunately I won't be able to get to that in the near future.

Share this post


Link to post
Share on other sites

Hi,

 

I tried that code mentioned in the above link. But something is not matching. I made changes in my wificlient.cpp file but did not get any fruitful result.

Can you or anyone from your engineering team provide me the code for connect() function in nonblocking mode? 

Share this post


Link to post
Share on other sites

Below is the replacement WiFiClient::connect() function. Right now the timeout is hardcoded but you can add an extra parameter for the timeout.

Please not that if you call WiFiClient::connect(const char* host, uint16_t port) a host lookup is done which eventually results in calling sl_NetAppDnsGetHostByName() this call seems to timeout after 20 sec if you do not have an internet connection (e.g. WAN cable unplugged from the router). Unfortunately this function does not feature a timeout. So to have control over the timeout, use the ip address of the host in the connect rather than the hostname.

int WiFiClient::connect(IPAddress ip, uint16_t port)
{
    int iRet = 0;
    //
    //this function should only be called once and only on the client side
    //
    if (_socketIndex != NO_SOCKET_AVAIL) {
        return false;
    }
    
    //
    //get a socket index and attempt to create a socket
    //note that the socket is intentionally left as BLOCKING. This allows an
    //abusive user to send as many requests as they want as fast as they can try
    //and it won't overload simplelink.
    //
    int socketIndex = WiFiClass::getSocket();
    if (socketIndex == NO_SOCKET_AVAIL) {
        return false;
    }

    int socketHandle = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP);
    if (socketHandle < 0) {
        return false;
    }

    //
    //connect the socket to the requested IP address and port. Check for success
    //

    long nonBlocking  = 1;
    iRet = sl_SetSockOpt(socketHandle, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking, sizeof(nonBlocking));

    SlSockAddrIn_t server = {0};
    server.sin_family = SL_AF_INET;
    server.sin_port = sl_Htons(port);
    server.sin_addr.s_addr = ip;
    iRet = sl_Connect(socketHandle, (SlSockAddr_t*)&server, sizeof(SlSockAddrIn_t));

    Serial.print("iRet = ");
    Serial.println(iRet);

    if (iRet < 0) {
        if (iRet != SL_EALREADY)
        {
            sl_Close(socketHandle);
            return false;
        }

       SlTimeval_t timeout;
       timeout.tv_sec = 10;
       timeout.tv_usec = 500;
 
       SlFdSet_t WriteFds;
       SL_FD_ZERO(&WriteFds);
       SL_FD_SET(socketHandle, &WriteFds);
       iRet = sl_Select(socketHandle + 1, NULL, &WriteFds, NULL, &timeout);

       if (iRet > 0) {
           if (SL_FD_ISSET(socketHandle, &WriteFds)) {
                iRet = sl_Connect(socketHandle, (SlSockAddr_t*)&server, sizeof(SlSockAddrIn_t));
                if(iRet < 0) {
                    sl_Close(socketHandle);
                    return false;
                } else {
                   // Success. Nothing to do.
                }
           }
       } else if(iRet == 0) {
           // Timeout
           sl_Close(socketHandle);
           return false;
       } else {
           // Connection error
           sl_Close(socketHandle);
           return false;
       }
    }

    int enableOption = 1;
    sl_SetSockOpt(socketHandle, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &enableOption, sizeof(enableOption));
    sl_SetSockOpt(socketHandle, SL_SOL_SOCKET, SL_SO_KEEPALIVE, &enableOption, sizeof(enableOption));

    //
    //we've successfully created a socket and connected, so store the
    //information in the arrays provided by WiFiClass
    //
    _socketIndex = socketIndex;
    WiFiClass::_handleArray[socketIndex] = socketHandle;
    WiFiClass::_typeArray[socketIndex] = TYPE_TCP_CLIENT;
    WiFiClass::_portArray[socketIndex] = port;
    return true;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now