Basic UDP Client

From Nutwiki
Revision as of 17:02, 27 October 2016 by Harald (Talk | contribs) (1 revision imported)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Overview

This example show how to create a client UDP socket and send simple messages with it. You will need a syslog server (such as the TFTPD32s built-in syslog server) or a network sniffer like Wireshark to see the output of this example.

Source Code

<source lang="c">

  1. include <io.h>
  2. include <stdio.h>
  3. include <string.h>
  4. include <time.h>
  1. include <dev/board.h>
  1. include <sys/timer.h>
  2. include <sys/socket.h>
  3. include <sys/confnet.h>
  4. include <sys/version.h>
  1. include <arpa/inet.h>
  1. include <net/route.h>
  2. include <netinet/in.h>
  1. include <pro/dhcp.h>
  1. define MY_SYSLOG "192.168.192.161"
  2. define BUFF_LEN 300

char udp_buff[BUFF_LEN]; UDPSOCKET *udp_sock; uint32_t udp_addr;

static char mon_name[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

int main(void) {

   u_long baud = 115200;
   time_t now;
   struct _tm *tip;
   size_t cnt;
   NutRegisterDevice(&DEV_DEBUG, 0, 0);
   freopen(DEV_DEBUG_NAME, "w", stdout);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   puts("\nUDP client example");
   if (NutRegisterDevice(&DEV_ETHER, 0, 0)) {
       puts("Registering " DEV_ETHER_NAME " failed.");
   }
   else if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
       puts("Configuring " DEV_ETHER_NAME " failed.");
   }
   /* store var representation of server name */
   udp_addr = inet_addr(MY_SYSLOG);
   /* create UDP socket */
   udp_sock = NutUdpCreateSocket(0);
   puts("The client is now running and sending UDP messages. Please open your syslog server log to see them.");
   for (;;) {
       /* fill the buffer with a syslog-esque message */
       time(&now);
       tip = localtime(&now);
       sprintf(udp_buff, "<6>%.3s%3d %02d:%02d:%02d udp-example This is the UDP example, you just received my message.",
               &mon_name[tip->tm_mon * 3], tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
       cnt = strlen(udp_buff);


       /* send the buffer to the syslog server */
       NutUdpSendTo(udp_sock, udp_addr, 514, udp_buff, cnt);
       NutSleep(10000);
   }
   return 0;

} </source>


Details

<source lang="c"> char udp_buff[BUFF_LEN]; UDPSOCKET *udp_sock; uint32_t udp_addr;

static char mon_name[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; </source> This may already catch your eye because of the unusual string for the month names. We'll use that string later on to put the months name in our homemade syslog message.

The other 3 variables are required for the actual udp socket we are going to use. udp_buff is a buffer for the data we're going to send, udp_sock will hold the pointer to our socket once we create it. udp_addr will store the internal converted version of the IP address we want to send to.

<source lang="c"> NutRegisterDevice(&DEV_DEBUG, 0, 0); freopen(DEV_DEBUG_NAME, "w", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud); puts("\nUDP client example");

if (NutRegisterDevice(&DEV_ETHER, 0, 0)) {

   puts("Registering " DEV_ETHER_NAME " failed.");

}

else if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {

   puts("Configuring " DEV_ETHER_NAME " failed.");

} </source> As always we set up the debug device, output a name for our application and then register all other devices we need. In this case we try to configure the network via DHCP since it is the easiest way for this example.

<source lang="c"> /* store var representation of server name */ udp_addr = inet_addr(MY_SYSLOG);

/* create UDP socket */ udp_sock = NutUdpCreateSocket(0); </source> Now we convert the string representation of the IP address into a number so we can use it later on.

And after that it gets interesting: NutUdpCreateSocket creates a UDP socket for us. Client applications should pass 0 here because they will be using a random port for sending anyway. We store the pointer to the socket in udp_sock.

In a real application you'd want to check for errors here but we won't do that now to keep it simple.

<source lang="c"> /* fill the buffer with a syslog-esque message */ time(&now); tip = localtime(&now); sprintf(udp_buff, "<6>%.3s%3d %02d:%02d:%02d udp-example This is the UDP example, you just received my message.",

       &mon_name[tip->tm_mon * 3], tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);

cnt = strlen(udp_buff); </source> This part isn't as confusing as it may look. We retrieve the time from the board and convert it to a datetime structure so it is easier to use with strings.

Then we fill the buffer for our udp_socket with a string that mimics the structure of a syslog message so your syslog server will pick it up. That's what we needed the time and the strange looking mon_name string above for. Using a formatting limit to just three characters and a pointer into the string we can extract the month name using the number in our datetime structure.

Next we store the length of the string in cnt so we know how many bytes to send.

This code was taken mostly from syslog.c so if you're interested on more details of the internal workings of the syslog functions, look it up there. We'll leave it at that for now.

<source lang="c"> /* send the buffer to the syslog server */ NutUdpSendTo(udp_sock, udp_addr, 514, udp_buff, cnt); </source> And now this line, although short, does all the udp magic. Well not exactly magic, it just sends our buffer to the target IP.

NutUdpSendTo takes some parameters: The socket we want to use. Of course that is the socket we created earlier. Then the address and port number (514 means syslog) we want to send to. Finally we pass the buffer and the length of the buffer so the function knows what exactly we want to send.

Please note that the UDP protocol does not guarantee that messages arrive at their destination, neither does it check if they did. So if you get a return value of 0 that means everything was okay when sending but it does not mean that the message actually arrived at its destination.

Output

File:Udpclient screen.jpg