Datagram Socket (UDP)

The figure below reproduces a diagram that introduces sample code using the typical socket functions for a UDP client-server application. The example uses the Micrium proprietary socket API function calls. A similar example could be written using the BSD socket API.

Figure - µC/TCP-IP Socket calls used in a typical UDP client-server application

The code in the listing below implements a UDP server. It opens a socket and binds an IP address, listens and waits for a packet to arrive at the specified port.

Datagram Server (UDP Server)

Listing - Datagram Server
#include  <Source/net_cfg_net.h>
#include  <Source/net_sock.h>
#include  <Source/net_app.h>
#include  <Source/net_util.h>
 
#define  UDP_SERVER_PORT  10001
#define  RX_BUF_SIZE         15
 
#ifdef  NET_IPv4_MODULE_EN
void  App_UDP_ServerIPv4 (void)
{
    NET_SOCK_ID          sock;
    NET_SOCK_ADDR_IPv4   server_sock_addr_ip;
    NET_SOCK_ADDR_IPv4   client_sock_addr_ip;
    NET_SOCK_ADDR_LEN    client_sock_addr_ip_size;
    NET_SOCK_RTN_CODE    rx_size;
    NET_SOCK_RTN_CODE    tx_size;
    NET_SOCK_DATA_SIZE   tx_rem;
    CPU_CHAR             rx_buf[RX_BUF_SIZE];
    CPU_INT32U           addr_any = NET_IPv4_ADDR_ANY;
    void                *p_buf;
    CPU_BOOLEAN          fault_err;
    NET_ERR              err;


                                                                /* ----------------- OPEN IPV4 SOCKET ----------------- */
    sock = NetSock_Open( NET_SOCK_ADDR_FAMILY_IP_V4,
                         NET_SOCK_TYPE_DATAGRAM,
                         NET_SOCK_PROTOCOL_UDP,
                        &err);
    if (err != NET_SOCK_ERR_NONE) {
        return;
    }


                                                                /* ------------ CONFIGURE SOCKET'S ADDRESS ------------ */
    NetApp_SetSockAddr((NET_SOCK_ADDR *)&server_sock_addr_ip,
                                         NET_SOCK_ADDR_FAMILY_IP_V4,
                                         UDP_SERVER_PORT,
                       (CPU_INT08U    *)&addr_any,
                                         NET_IPv4_ADDR_SIZE,
                                        &err);
    switch (err) {
        case NET_APP_ERR_NONE:
            break;

        case NET_APP_ERR_FAULT:
        case NET_APP_ERR_NONE_AVAIL:
        case NET_APP_ERR_INVALID_ARG:
        default:
            NetSock_Close(sock, &err);
            return;
    }


                                                                /* ------------------- BIND SOCKET -------------------- */
    NetSock_Bind(                  sock,
                 (NET_SOCK_ADDR *)&server_sock_addr_ip,
                                   NET_SOCK_ADDR_SIZE,
                                  &err);
    if (err != NET_SOCK_ERR_NONE) {
        NetSock_Close(sock, &err);
        return;
    }

    fault_err = DEF_NO;
    do {

                                                                /* ----- WAIT UNTIL RECEIVING DATA FROM A CLIENT ------ */
        client_sock_addr_ip_size = sizeof(client_sock_addr_ip);
        rx_size = NetSock_RxDataFrom(                  sock,
                                                       rx_buf,
                                                       RX_BUF_SIZE,
                                                       NET_SOCK_FLAG_NONE,
                                     (NET_SOCK_ADDR *)&client_sock_addr_ip,
                                                      &client_sock_addr_ip_size,
                                                       DEF_NULL,
                                                       DEF_NULL,
                                                       DEF_NULL,
                                                      &err);
        switch (err) {
            case NET_SOCK_ERR_NONE:
                 tx_rem = rx_size;
                 p_buf  = rx_buf;
                                                                /* ----- TRANSMIT THE DATA RECEIVED TO THE CLIENT ----- */
                 do {
                     tx_size = NetSock_TxDataTo(                  sock,
                                                                  p_buf,
                                                                  tx_rem,
                                                                  NET_SOCK_FLAG_NONE,
                                                (NET_SOCK_ADDR *)&client_sock_addr_ip,
                                                                  client_sock_addr_ip_size,
                                                                 &err);
                     tx_rem -= tx_size;
                     p_buf  += tx_size;
                 } while (tx_rem > 0);
                 break;
            case NET_SOCK_ERR_RX_Q_EMPTY:
            case NET_ERR_FAULT_LOCK_ACQUIRE:
                 break;

            default:
                fault_err = DEF_YES;
                break;
        }
    } while (fault_err == DEF_NO);
 

                                                                /* ------------- FATAL FAULT SOCKET ERROR ------------- */
    NetSock_Close(sock, &err);                                  /* This function should be reached only when a fatal ...*/
                                                                /* fault error has occurred.                            */
}
#endif
 
 
/*
*********************************************************************************************************
*                                         App_UDP_ServerIPv6()
*
* Description : UDP Echo server:
*
*                   (a) Open a socket.
*                   (b) Configure socket's address.
*                   (c) Bind that socket.
*                   (d) Receive data on the socket.
*                   (e) Transmit to source the data received.
*                   (f) Close socket on fatal fault error.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : none.
*
* Note(s)     : none.
*********************************************************************************************************
*/
#ifdef  NET_IPv6_MODULE_EN
void  App_UDP_ServerIPv6 (void)
{
    NET_SOCK_ID          sock;
    NET_SOCK_ADDR_IPv6   server_sock_addr_ip;
    NET_SOCK_ADDR_IPv6   client_sock_addr_ip;
    NET_SOCK_ADDR_LEN    client_sock_addr_ip_size;
    NET_SOCK_RTN_CODE    rx_size;
    NET_SOCK_RTN_CODE    tx_size;
    NET_SOCK_DATA_SIZE   tx_rem;
    CPU_CHAR             rx_buf[RX_BUF_SIZE];
    void                *p_buf;
    CPU_BOOLEAN          fault_err;
    NET_ERR              err;
 

                                                                /* ----------------- OPEN IPV6 SOCKET ----------------- */
    sock = NetSock_Open( NET_SOCK_ADDR_FAMILY_IP_V6,			/* IPv6 Socket family.   								*/
                         NET_SOCK_TYPE_DATAGRAM,				/* Datagram socket.										*/
                         NET_SOCK_PROTOCOL_UDP,					/* UDP protocol.										*/
                        &err);
    if (err != NET_SOCK_ERR_NONE) {
        return;
    }


                                                                /* ------------ CONFIGURE SOCKET'S ADDRESS ------------ */
                                                                /* Populate the NET_SOCK_ADDR_IP structure for the ...  */
                                                                /* server address and port, and convert it to ...       */
                                                                /* network order.                                       */
    NetApp_SetSockAddr((NET_SOCK_ADDR *)&server_sock_addr_ip,	
                                         NET_SOCK_ADDR_FAMILY_IP_V6,
                                         UDP_SERVER_PORT,
                       (CPU_INT08U    *)&NET_IPv6_ADDR_ANY,
                                         NET_IPv6_ADDR_SIZE,
                                        &err);
    switch (err) {
        case NET_APP_ERR_NONE:
            break;

        case NET_APP_ERR_FAULT:
        case NET_APP_ERR_NONE_AVAIL:
        case NET_APP_ERR_INVALID_ARG:
        default:
            NetSock_Close(sock, &err);
            return;
    }


                                                                /* ------------------- BIND SOCKET -------------------- */
    NetSock_Bind(                  sock,                        /* Bind the newly created socket to the address and ... */
                 (NET_SOCK_ADDR *)&server_sock_addr_ip,         /* port specified by server_sock_addr_ip.               */
                                   NET_SOCK_ADDR_SIZE,
                                  &err);
    if (err != NET_SOCK_ERR_NONE) {
        NetSock_Close(sock, &err);
        return;
    }

    fault_err = DEF_NO;
    do {
                                                                /* ----- WAIT UNTIL RECEIVING DATA FROM A CLIENT ------ */
        client_sock_addr_ip_size = sizeof(client_sock_addr_ip);
        rx_size = NetSock_RxDataFrom(                  sock,    /* Receive data from any host on port UDP_SERVER_PORT.  */  
                                                       rx_buf,
                                                       RX_BUF_SIZE,
                                                       NET_SOCK_FLAG_NONE,
                                     (NET_SOCK_ADDR *)&client_sock_addr_ip,
                                                      &client_sock_addr_ip_size,
                                                       DEF_NULL,
                                                       DEF_NULL,
                                                       DEF_NULL,
                                                      &err);
        switch (err) {
            case NET_SOCK_ERR_NONE:
                 tx_rem = rx_size;
                 p_buf  = rx_buf;
                 do {
                                                                /* ------- TRANSMIT RECEIVED DATA TO THE CLIENT ------- */
                                                                /* Transmit data to IP address and port of the client.  */
                     tx_size = NetSock_TxDataTo(                  sock,
                                                                  p_buf,
                                                                  tx_rem,
                                                                  NET_SOCK_FLAG_NONE,
                                                (NET_SOCK_ADDR *)&client_sock_addr_ip,
                                                                  client_sock_addr_ip_size,
                                                                 &err);
                     tx_rem -= tx_size;
                     p_buf  += tx_size;
                 } while (tx_rem > 0);
                 break;
            case NET_SOCK_ERR_RX_Q_EMPTY:
            case NET_ERR_FAULT_LOCK_ACQUIRE:
                 break;

            default:
                fault_err = DEF_YES;
                break;
        }        
    } while (fault_err == DEF_NO);								/* Process more client requests.						*/

                                                                /* ------------- FATAL FAULT SOCKET ERROR ------------- */
    NetSock_Close(sock, &err);                                  /* This function should be reached only when a fatal ...*/
                                                                /* fault error has occurred.                            */
}
#endif
  1. Open a datagram socket (UDP protocol).
  2. Populate the NET_SOCK_ADDR_IP structure for the server address and port, and convert it to network order.
  3. Bind the newly created socket to the address and port specified by server_sock_addr_ip.
  4. Receive data from any host on port DATAGRAM_SERVER_PORT.
  5. Close the socket.


Datagram Client (UDP Client)

The code in the listing below implements a UDP client. It sends a ‘Hello World!’ message to a server that listens on the UDP_SERVER_PORT.

Listing - Datagram Server
#define  UDP_SERVER_IP_ADDR   "192.168.1.100"
#define  UDP_SERVER_PORT               10001
#define  UDP_SERVER_TX_STR     "Hello World!"
 
 
CPU_BOOLEAN  TestUDPClient (void)
{
    NET_SOCK_ID         sock;
    NET_IP_ADDR         server_ip_addr;
    NET_SOCK_ADDR_IP    server_sock_addr_ip;
    NET_SOCK_ADDR_LEN   server_sock_addr_ip_size;
    CPU_CHAR           *pbuf;
    CPU_INT16S          buf_len;
    NET_SOCK_RTN_CODE   tx_size;
    NET_ERR             err;
    pbuf    = UDP_SERVER_TX_STR;
    buf_len = Str_Len(UDP_SERVER_TX_STR);
 
    sock = NetSock_Open( NET_SOCK_ADDR_FAMILY_IP_V4,                                           (1)
                         NET_SOCK_TYPE_DATAGRAM,
                         NET_SOCK_PROTOCOL_UDP,
                        &err);
    if (err != NET_SOCK_ERR_NONE) {
        return (DEF_FALSE);
    }
 
    server_ip_addr = NetASCII_Str_to_IP(UDP_SERVER_IP_ADDR, &err);                             (2)
    if (err != NET_ASCII_ERR_NONE) {
        NetSock_Close(sock, &err);
        return (DEF_FALSE);
    }
    server_sock_addr_ip_size = sizeof(server_sock_addr_ip);                                    (3)
    Mem_Clr((void     *)&server_sock_addr_ip,
            (CPU_SIZE_T) server_sock_addr_ip_size);
    server_sock_addr_ip.AddrFamily = NET_SOCK_ADDR_FAMILY_IP_V4;
    server_sock_addr_ip.Addr       = NET_UTIL_HOST_TO_NET_32(server_ip_addr); 
    server_sock_addr_ip.Port       = NET_UTIL_HOST_TO_NET_16(UDP_SERVER_PORT);
 
    tx_size = NetSock_TxDataTo((NET_SOCK_ID ) sock,                                            (4)
                               (void *) pbuf,
                               (CPU_INT16S ) buf_len,
                               (CPU_INT16S ) NET_SOCK_FLAG_NONE,
                               (NET_SOCK_ADDR *)&server_sock_addr_ip,
                               (NET_SOCK_ADDR_LEN) sizeof(server_sock_addr_ip),
                               (NET_ERR *)&err);
 
    NetSock_Close(sock, &err);                                                                 (5)
    if (err != NET_SOCK_ERR_NONE) {
        return (DEF_FALSE);
    }
    return (DEF_TRUE);
}
  1. Open a datagram socket (UDP protocol).
  2. Convert an IPv4 address from ASCII dotted-decimal notation to a network protocol IPv4 address in host-order.
  3. Populate the NET_SOCK_ADDR_IP structure for the server address and port, and convert it to network order.
  4. Transmit data to host DATAGRAM_SERVER_IP_ADDR on port DATAGRAM_SERVER_PORT.
  5. Close the socket.