Simple C UDP Broadcast Client
How to write a simple C UDP broadcast test program.
Recently I had a project that required graphing several values from a motor control PID loop. The PID loop was running on embedded hardware in a C process. This is the first part of several describing the general approach taken. The examples provided in this and the next posts are for example purposes and not robust enough for production.
All the development and testing has been done on linux.
Sample Application
The sample application can be found here.
User Datagram Protocol
The User Datagram Protocol (UDP) is a lightweight connectionless messaging protocol. It sits like TCP above IP in the protocol stack. Unlike TCP, it has no guarantee that packets will arrive or be in order.
IP Broadcast
An IP broadcast is a packet sent to everyone on the originating subnet. At the IP layer you send a broadcast by sending packets to a specific address.
According to wikipedia:
The broadcast address for any IPv4 host can be obtained by taking the bit complement
(bitwise NOT) of the subnet mask and then performing a bitwise OR operation with the
host's IP address. A shortcut to this process (for common masks using only 0 and 1
bit placements) is to simply take the host's IP address and set all bits in the host
identifier portion of the address (any bit positions which hold a 0 in the subnet
mask) to 1."
I am going to be broadcasting from IP address 192.168.0.216 with a subnet mask of 255.255.255.0. I will use the broadcast address of 192.168.0.255.
The Client Program
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
#include <math.h>
#include <time.h>
static const int BROADCAST_PORT = 9999;
static const char BROADCAST_IP[] = "192.168.0.255";
static const int RATE_MS = 50000000;
static int open_broadcast_socket (int *broadcast_socket, struct sockaddr_in *host_addr){
int trueval = 1;
memset(host_addr, 0, sizeof(struct sockaddr_in));
host_addr->sin_family = AF_INET;
host_addr->sin_addr.s_addr = inet_addr(BROADCAST_IP);
host_addr->sin_port = htons (BROADCAST_PORT);
*broadcast_socket = socket (PF_INET, SOCK_DGRAM, getprotobyname ("udp")->p_proto);
if (broadcast_socket < 0){
printf("Error creating broadcast socket.\n");
}
setsockopt (*broadcast_socket, SOL_SOCKET, SO_REUSEADDR, &trueval, sizeof (trueval));
setsockopt (*broadcast_socket, SOL_SOCKET, SO_BROADCAST, &trueval, sizeof (trueval));
if (bind (*broadcast_socket, (const struct sockaddr *)host_addr, sizeof (struct sockaddr_in)) < 0){
printf("Couldn't bind to port %d \n", BROADCAST_PORT);
return -1;
}
return 0;
}
#pragma pack(1)
typedef struct _data_packet{
double i;
double sin;
double cos;
} data_packet_t;
#pragma pack()
void main(void){
data_packet_t data_packet;
int broadcast_sock = 0;
struct sockaddr_in host_addr;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = RATE_MS;
open_broadcast_socket(&broadcast_sock, &host_addr);
for(double i = 0 ;; i += .1){
data_packet.i = i;
data_packet.sin = sin(i);
data_packet.cos = cos(i);
sendto(broadcast_sock,
&data_packet,
sizeof(data_packet),
0,
(struct sockaddr *) &host_addr,
sizeof(host_addr));
nanosleep(&ts, &ts);
}
}
Compile and run the client on a machine different from the one you are on. Open wireshark, choose the interface attached to the 192.168.0 subnet.
WARNING
Running the client on the same machine as the one you are trying to receive the broadcast packets from will not work. The loopback interface will not receive the broadcast packets back from the network.

UDP Broadcasts Captured In Wireshark
Conclusion
You now have a program broadcasting on 192.168.0.255 port 9999. It is sending two floats sin and cos in a data packet.
Next we will begin writing an Electron App to parse and graph the stream of data.