CC3220SF: Client programs are periodically reconnecting to CC3220SF based server

Part Number: CC3220SF

Hello!

I wrote a program for CC3220SF LAUNCHXL based on the network terminal and cloud ota examples.

The program works as follows:
1. The client program running on the computer connects to LaunchPad server socket by WiFi and sends commands to the device
2. LaunchPad decodes and transmits commands to the device by UART
3. The device responds to commands by UART
4. LaunchPad encrypts and transmits data by WiFi to an client program

When there is only one connection to the LaunchPad, this program works stably and there is no reconnection for at least a day.
When there is more than one connection, client programs are periodically reconnected to the LaunchPad.
Reconnections become more frequent when connecting a new copy of the client program.
After a while, something stabilizes and reconnections become less frequent.
When connecting another copy of the client program, the situation repeats.
If I remove the line usleep(1000); after for(i = 0; i <16; i ++) , the number of reconnections increases dramatically.
The client program reconnects if there is no response from the server within 1 second.

Why client programs are reconnecting, when there is more than one connection?

Code Composer Studio 10.2.0, SimpleLink CC32xx SDK 4.30.00.06

Here's my source code regarding data exchange by WiFi:

int32_t TCPServerInit(sockAddr_t *sAddr, uint16_t port)
{
    int32_t sock;
    int32_t status;
    int32_t nonBlocking = TRUE;
    /* Contains the local ip address and port */
    SlSockAddr_t    *sa;
    int32_t addrSize;


    /* filling the TCP server socket address */
    sAddr->in4.sin_family = SL_AF_INET;

    /* Set the server's port:
       We'll receive connection requests on this port */
    sAddr->in4.sin_port = sl_Htons(port);
    sAddr->in4.sin_addr.s_addr = SL_INADDR_ANY;

    sa = (SlSockAddr_t*)sAddr;
    addrSize = sizeof(SlSockAddrIn_t);

    /*
     *  Open a TCP socket:
     *  Since TCP is a connection oriented channel,
     *  the opened socket would serve as 'welcome' socket,
     *  on which we'll receive connection requests from clients.
     */
    sock = sl_Socket(sa->sa_family, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
    ASSERT_ON_ERROR(sock, SL_SOCKET_ERROR);

    /* Bind socket to server's port */
    status = sl_Bind(sock, sa, addrSize);
    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                   SL_SOCKET_ERROR);
        sl_Close(sock);
        return(-1);
    }

   /* 'Listen' signify that wer'e ready to receive connection's from clients */
    status = sl_Listen(sock, 0);
    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                   SL_SOCKET_ERROR);
        sl_Close(sock);
        return(-1);
    }

    /* Set socket as non-blocking socket (if needed):
     * Non-blocking sockets allows user to handle other tasks rather than block
     * on socket API calls.
     * If an API call using the Non-blocking socket descriptor
     * returns 'SL_ERROR_BSD_EAGAIN' -
     * this indicate that the user should try the API again later.
     */
    nonBlocking = TRUE;
    status =
        sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking,
                      sizeof(nonBlocking));
    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                   SL_SOCKET_ERROR);
        return(-1);
    }

    return sock;
}

typedef union
{
    uint32_t ipv4;          /* Ipv4 Address */
    uint8_t ipv6[16];       /* Ipv6 Address */
}ip_t;


SlSockAddr_t *IP2SlSockAddr(uint8_t sl_fa, uint16_t portNumber, ip_t ipAddress, sockAddr_t *sAddr)
{
    // filling the TCP server socket address
    sAddr->in4.sin_family = SL_AF_INET;

    // Since this is the client's side,
    // we must know beforehand the IP address
    // and the port of the server wer'e trying to connect.
    sAddr->in4.sin_port = sl_Htons((unsigned short)portNumber);
    sAddr->in4.sin_addr.s_addr = sl_Htonl((unsigned int)ipAddress.ipv4);

    return (SlSockAddr_t*)sAddr;
}

int32_t TCPClientInit(uint8_t sa_family)
{
    int32_t sock;
    int32_t status;
    int32_t nonBlocking;

    // Get socket descriptor - this would be the
    // socket descriptor for the TCP session.
    sock = sl_Socket(sa_family, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
    ASSERT_ON_ERROR(sock, SL_SOCKET_ERROR);

    // Set socket as non-blocking socket (if needed):
    // Non-blocking sockets allows user to handle
    // other tasks rather than block
    // on socket API calls.
    // If an API call using the Non-blocking socket descriptor
    // returns 'SL_ERROR_BSD_EAGAIN' -
    // this indicate that the user should try the API again later.
    nonBlocking = TRUE;
    status = sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking, sizeof(nonBlocking));

    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                   SL_SOCKET_ERROR);
        sl_Close(sock);
        return(-1);
    }

    return sock;
}

void *appThread(void *arg0)
{
    uint8_t run_first = 1;

    int32_t server_sock;

    /* Contains the ip address and port of the connected peer. */
    static SlSockAddr_t    *csa;
    static sockAddr_t sAddr;
    static int32_t addrSize;
    int32_t ret;
    uint32_t ans;
    int32_t newsock = -1;

    static uint8_t server_states[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    uint8_t *psrvstate;
    uint32_t uart_send_size;
    uint32_t *pusendsz;

#define server_state *psrvstate

    static uint32_t socket_sizes[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    uint32_t *psocksz;

#define socket_size *psocksz

    static uint32_t socket_flags[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    uint32_t *psockfl;

#define socket_flag *psockfl

    int32_t status;
    static int32_t client_socks[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int32_t *pclsock;
    static uint8_t client_states[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    uint8_t *pclstate;

#define client_sock *pclsock
#define client_state *pclstate

    uint8_t queue_state;
    uint16_t queue_size;
    uint8_t *queue_bufptr;
    static uint8_t queue_items[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

#define queue_item queue_items[i]

...

    while(1)
    {
        usleep(1000);

        if(run_first)
        {
            server_sock = TCPServerInit(&sAddr, 2612);

            csa = (SlSockAddr_t*)&sAddr;
            addrSize = sizeof(SlSockAddrIn_t);

            if(server_sock >= 0)
                run_first = 0;
        }
        else
        {
            newsock = sl_Accept(server_sock, csa, (SlSocklen_t*)&addrSize);

            if(newsock == SL_ERROR_BSD_EAGAIN)
            {
                //break;
            }
            else if(newsock < 0)
            {
                server_states[newsock] = 0;
            }
            else
            {
                UART_PRINT("Connected to client %d: ", newsock);

                sAddr.in4.sin_addr.s_addr = sl_Htonl(sAddr.in4.sin_addr.s_addr);
                PrintIPAddress(FALSE,(void*)&sAddr.in4.sin_addr);

                UART_PRINT(lineBreak);

                if(newsock < 16)
                {
                    server_states[newsock] = 1;
                }
            }

uint8_t i = 0;
            for(i = 0; i < 16; i++)
            {
usleep(1000);

                socketBuf = sockbuf[i];
                psrvstate = &server_states[i];
                psocksz = &socket_sizes[i];
                psockfl = &socket_flags[i];

                switch(server_state)
                {
                case 0:
                    // Not connected
                    break;
                case 1:
                    ret = sl_Recv(i, socketBuf, MAX_BUF_SIZE, 0);

                    if(ret == SL_ERROR_BSD_EAGAIN)
                    {
                        break;
                    }
                    else if(ret < 0)
                    {
                        UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, ret,
                                   BSD_SOCKET_ERROR);
                        UART_PRINT("Socket %d closed\n\r", i);

                        sl_Close(i);

                        server_state = 0;

                        break;
                    }
                    else if(ret == 0)
                    {
                        UART_PRINT("TCP Client (socket %d) closed the connection \n\r", i);

                        sl_Close(i);

                        server_state = 0;

                        break;
                    }
					
                    uart_send_size = ret;

                    queue_item = AddToQueue(socketBuf, uart_send_size, socketBuf, 0);

                    server_state = 2;

                    break;
                case 2:
                    queue_state = QueueState(queue_item);

                    if(queue_state >= ready)
                    {
                        queue_size = QueueSize(queue_item);
                        socket_size = queue_size;
                    }
                    else
                        break;
                case 3:
                    Encrypt((char*)socketBuf, (char*)socketBuf, socket_size);
					
                    ret = sl_Send(i, socketBuf, socket_size, 0);
                    if(ret == SL_ERROR_BSD_EAGAIN)
                    {
                        break;
                    }
                    else if(ret < 0)
                    {
                        UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, ret,
                                   SL_SOCKET_ERROR);
                        UART_PRINT("Socket %d closed\n\r", i);

                        sl_Close(i);

                        server_state = 0;

                        break;
                    }

                    server_state = 1;

                    break;
                }
            }
        }
    }
}
 

Also, sometimes there is an error Error [-2] at line [1531] in function [CheckLanConnection] in the file cloud_ota.c
Line 1531 corresponds to the code

    /* Ping the GW */
    retVal = sl_NetAppPing((SlNetAppPingCommand_t*)&pingParams, \
                           SL_AF_INET, (SlNetAppPingReport_t*)&pingReport, \
                           SimpleLinkPingReport);
    ASSERT_ON_ERROR(retVal);

When trying to update, the program rarely hangs on the line LOOP_FOREVER (); in the cloud_ota.c file

        if(NULL != pEntry->p_evtHndl)
        {
            if(pEntry->p_evtHndl() < 0)
            {
                UART_PRINT("Event handler failed..!! \r\n");
                LOOP_FOREVER();
            }
        }


  • Hi,

    How much data is being sent / received by each of the clients?

    Is it possible that 2 clients throughput is close to the over-the-air bandwidth which cause the disconnections? or maybe your application is starving one connection (e.g. you are not getting to read from it for a long time, till the buffer gets full and the peer disconnects eventually). 

    We will need to check air sniffer logs or NWP logs (see chapter 20.1 in www.ti.com/.../swru455).

    Who triggers the disconnection? the launchpad or the clients?

    i'm not sure what is the -2 error code, please debug inside the sl_NetAppPing (sources are available in the simplelink project). The NWP log may help to understand this as well. 

    The  pEntry->p_evtHndl() issue also needs investigation. Please check the value (should be a function address). Also  check the values of "pCtx->currentState" and "event" in such case.

    Br,

    Kobi