This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432E401Y: UDP: using sendto() without recvfrom()

Part Number: MSP432E401Y


Hi folks. I am trying to get a UDP send-only demo up and running. I started with the project at http://dev.ti.com/tirex/explore/node?node=ADB7cEDeelFwfWnYrD6CnQ__J4.hfJy__LATEST and have modified udpEcho.c so that it looks like:

/*
 * Copyright (c) 2015-2018, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *    ======== udpEcho.c ========
 *    Contains BSD sockets code.
 */

#include <pthread.h>
/* BSD support */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <fcntl.h>

#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>

#include <ti/net/slnetutils.h>

#include <ti/display/Display.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>

/* Example/Board Header files */
#include "Board.h"

#define UDPPACKETSIZE 1472

extern Display_Handle display;

extern void fdOpenSession();
extern void fdCloseSession();
extern void *TaskSelf();

/*
 *  ======== echoFxn ========
 *  Echoes UDP messages.
 *
 */
void *echoFxn(void *arg0)
{
    int                bytesSent;
    int                bytesRcvd;
    int                status;
    int                sockfd;
    struct sockaddr_in localAddr;
    struct sockaddr_in clientAddr;
    socklen_t          addrlen;
    char               buffer[UDPPACKETSIZE];
    uint16_t           portNumber = *(uint16_t *)arg0;
    char mybuffer[256];

    fdOpenSession(TaskSelf());

    Display_printf(display, 0, 0, "UDP send demo started\n");

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        Display_printf(display, 0, 0, "Error: socket not created.\n");
        goto shutdown;
    }

    memset(&localAddr, 0, sizeof(localAddr));
    localAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localAddr.sin_port = htons(portNumber);

    status = bind(sockfd, (struct sockaddr *)&localAddr, sizeof(localAddr));
    if (status == -1) {
        Display_printf(display, 0, 0, "Error: bind failed.\n");
        goto shutdown;
    }

//    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL)|O_NONBLOCK) < 0) {
//        Display_printf(display, 0, 0, "Error: fcntl failed.\n");
//    }
//    char broadcast = '1';
//    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0) {
//        Display_printf(display, 0, 0, "Error: setsockopt failed.\n");
//    }
//    bytesRcvd = recvfrom(sockfd, buffer, UDPPACKETSIZE, MSG_DONTWAIT, (struct sockaddr *)&clientAddr, &addrlen);
//    sprintf(mybuffer, "recvfrom returned (%d)", bytesRcvd);
//    Display_printf(display, 0, 0, mybuffer);

    recvfrom(sockfd, buffer, UDPPACKETSIZE, 0, (struct sockaddr *)&clientAddr, &addrlen);

    char* test_buffer = "This is a test!";

    Display_printf(display, 0, 0, "Going into loop.\n");
    while (1) {
        addrlen = sizeof(clientAddr);

        bytesSent = sendto(sockfd, test_buffer, strlen(test_buffer), 0, (struct sockaddr *)&clientAddr, addrlen);

        if (bytesSent < 0 || bytesSent != strlen(test_buffer)) {
            sprintf(mybuffer, "Error: sendto failed (%d)", bytesSent);
            Display_printf(display, 0, 0, mybuffer);
            // goto shutdown;
        }
        else {
            sprintf(mybuffer, "Send was successful.");
            Display_printf(display, 0, 0, mybuffer);
        }
    }

shutdown:
    if (sockfd != -1) {
        close(sockfd);
    }

    fdCloseSession(TaskSelf());

    return (NULL);
}

This code runs succesfully as expected, but if I remove the call to recvfrom(), then every call to sendto() in the loop fails. So my questions are:

Why is sendto() dependent on recvfrom() running first? 

How can I run sendto() without calling recvfrom()? Is there something that needs to be configured in the NDK stack?

I have also tried setting recvfrom() to be nonblocking, but have not been successful with that.

  • Attaching the CCS project in case anybody wants to play around with it:
    udpecho_freertos_pin_toggle_forum_post.zip

  • The clientAddr is sourced from the recvfrom() api in a connection-less socket.  If you know what the clientAddr is, then you could populate it before calling the sendTo api.

    https://www.geeksforgeeks.org/udp-server-client-implementation-c/

    Regards,

    Chris

  • Thanks for your reply! I think that was exactly the issue. Here's my updated code, working as desired:

    /*
     * Copyright (c) 2015-2018, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *    ======== udpEcho.c ========
     *    Contains BSD sockets code.
     */
    
    #include <pthread.h>
    /* BSD support */
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <sys/select.h>
    #include <fcntl.h>
    
    #include <string.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <unistd.h>
    
    #include <ti/net/slnetutils.h>
    
    #include <ti/display/Display.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    
    /* Example/Board Header files */
    #include "Board.h"
    
    #define UDPPACKETSIZE 1472
    
    extern Display_Handle display;
    
    extern void fdOpenSession();
    extern void fdCloseSession();
    extern void *TaskSelf();
    
    /*
     *  ======== echoFxn ========
     *  Echoes UDP messages.
     *
     */
    void *echoFxn(void *arg0)
    {
        int                bytesSent;
        int                status;
        int                sockfd;
        struct sockaddr_in localAddr;
        struct sockaddr_in clientAddr;
        socklen_t          addrlen;
        uint16_t           portNumber = *(uint16_t *)arg0;
        char mybuffer[256];
    
        fdOpenSession(TaskSelf());
    
        Display_printf(display, 0, 0, "UDP send demo started\n");
    
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1) {
            Display_printf(display, 0, 0, "Error: socket not created.\n");
            goto shutdown;
        }
    
        memset(&localAddr, 0, sizeof(localAddr));
        localAddr.sin_family = AF_INET;
        localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        localAddr.sin_port = htons(portNumber);
    
        clientAddr.sin_family = AF_INET;
        clientAddr.sin_port = htons(1000);
        clientAddr.sin_addr.s_addr = inet_addr("192.168.1.69");
        addrlen = sizeof(clientAddr);
    
        status = bind(sockfd, (struct sockaddr *)&localAddr, sizeof(localAddr));
        if (status == -1) {
            Display_printf(display, 0, 0, "Error: bind failed.\n");
            goto shutdown;
        }
    
        char* test_buffer = "This is a test!";
    
        int count = 0;
        Display_printf(display, 0, 0, "Going into loop.\n");
        while (1) {
    
            bytesSent = sendto(sockfd, test_buffer, strlen(test_buffer), 0, (struct sockaddr *)&clientAddr, addrlen);
    
            if (bytesSent < 0 || bytesSent != strlen(test_buffer)) {
                sprintf(mybuffer, "Error: sendto failed (%d)", bytesSent);
                Display_printf(display, 0, 0, mybuffer);
                goto shutdown;
            }
            else {
                sprintf(mybuffer, "Send was successful %5d.", count++);
                Display_printf(display, 0, 0, mybuffer);
            }
    
            sleep(1);
        }
    
    shutdown:
        if (sockfd != -1) {
            close(sockfd);
        }
    
        fdCloseSession(TaskSelf());
        return (NULL);
    }

**Attention** This is a public forum