Introduction
Welcome back! In our last two lessons, you did an excellent job building a complete TCP client-server application. You've mastered the connection-oriented model, where connect(), listen(), and accept() work together to create a stable, reliable communication channel, much like a phone call.
Today, we shift gears to TCP's counterpart: UDP (User Datagram Protocol). UDP is connectionless and operates more like sending a postcard. You write the message, put the address on it, and drop it in the mail. There's no prior setup, and you don't get a confirmation that it arrived. This model is ideal for applications where speed is critical and losing an occasional packet isn't a disaster, such as in DNS lookups, online gaming, or video streaming.
Our goal in this lesson is to describe the socket API calls for a typical UDP client and server. We won't be writing the full code just yet; instead, we'll focus on understanding the what and why of the functions that make UDP's "fire-and-forget" model possible. This will lay the groundwork for our next lesson, where you'll implement these concepts in C.
The UDP Model: Connectionless Communication
In the TCP world, you established a connection first, and then you could simply send() and recv() data through that established pipe. The operating system handled addressing for you after the initial setup.
UDP is different. Since there is no persistent connection, every single datagram (the UDP equivalent of a packet) must be individually addressed. This fundamentally changes the API calls we use.
Let's look at a diagram that contrasts the two models.

The key takeaways from this model are:
- No Handshake: The client doesn't
connect()and the server doesn'tlisten()oraccept(). They just start sending and receiving. - New Functions: The generic
send()andrecv()are replaced bysendto()andrecvfrom(). As their names imply, they include parameters for address information. - Server
bind()is still crucial: The server still needs tobind()to a specific, well-known port so clients know where to send their datagrams.
The C API for UDP
Let's dive into the specifics of the C functions. We'll watch a video that walks through building a UDP sender (client) and receiver (server) in C. This will give you a practical look at the API calls in action.
How to Send and Receive UDP packets (in C)
The video 'How to Send and Receive UDP packets (in C)' by Jacob Sorber is an excellent, practical walkthrough. It demonstrates exactly the API calls we are discussing and shows how they fit into a working program.
Watch the entire video (around 23 minutes). As you watch, focus on identifying the purpose of these key functions: Sender (Client) Side: socket() with SOCK_DGRAM Preparing the server's sockaddr_in struct The sendto() function and its arguments Receiver (Server) Side: bind() to a specific port The recvfrom() function and how it provides the sender's address Using the sender's address to send a reply back
Now that you've seen the code in action, let's break down the API calls for the server and client methodically.
The UDP Server: socket, bind, recvfrom, sendto
A UDP server's job is to wait at a known port, receive a datagram from any client, process it, and send a reply back to that specific client.
-
socket(): The server first creates its communication endpoint.int sockfd = socket(AF_INET, SOCK_DGRAM, 0);The only difference from your TCP code is
SOCK_DGRAM. This tells the operating system to create a socket that sends and receives connectionless datagrams using UDP. -
bind(): The server then claims a port.struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(9800); bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));This is identical to the TCP server's
bind()call. It's how a client can find the server—by sending a packet to the server machine's IP address at port9800. -
recvfrom(): This is the heart of the UDP server. It replaces theaccept()/recv()combination from TCP.char buffer[1024]; struct sockaddr_in cliaddr; socklen_t len = sizeof(cliaddr); int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *) &cliaddr, &len);The
recvfromfunction does two critical things:- It blocks and waits for a datagram to arrive at the bound port (
9800). - When a datagram arrives, it copies the data into
bufferand, crucially, it fills thecliaddrstruct with the IP address and port of the client who sent it.
- It blocks and waits for a datagram to arrive at the bound port (
-
sendto(): To send a reply, the server uses the address information it just obtained fromrecvfrom.sendto(sockfd, "Reply message", 13, 0, (struct sockaddr *) &cliaddr, len);The server uses the same socket (
sockfd) to send the reply. It provides the client's address (cliaddr) as the destination, ensuring the reply goes back to the correct sender.
This request-reply sequence often happens inside a while(1) loop, allowing the server to handle datagrams from many different clients, one after another.
For a concise, text-based summary of these functions, you can refer to the following resource.
The 'Sockets Tutorial' webpage provides a clear, text-based explanation of the differences in a datagram socket server.
Read the sections explaining the differences in the UDP server code. Focus on the description of the recvfrom() and sendto() system calls and their arguments. This will reinforce what you saw in the video.
The UDP Client: socket, sendto, recvfrom
A UDP client's job is simpler. It doesn't need to establish a connection; it just prepares a message and sends it directly to the server's known address.
-
socket(): The client creates a datagram socket, just like the server.int sockfd = socket(AF_INET, SOCK_DGRAM, 0); -
bind()(Optional): Unlike the server, the client typically does not callbind(). When the client callssendto()for the first time, the operating system will automatically assign a temporary, unused port number (an ephemeral port) to its socket. This is sufficient because the server will learn this temporary address viarecvfrom(). -
sendto(): This is the client's primary action.struct sockaddr_in servaddr; // ... code to fill servaddr with the server's IP and port ... char *message = "Hello, Server!"; sendto(sockfd, message, strlen(message), 0, (struct sockaddr *) &servaddr, sizeof(servaddr));The client must know the server's address ahead of time and populate the
servaddrstruct accordingly. It then callssendto()to fire off the datagram. -
recvfrom(): After sending its request, the client usually wants a reply.char buffer[1024]; int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL);The client calls
recvfrom()on its own socket to wait for the server's response. Notice that the last two arguments can beNULLif the client doesn't care about re-confirming which address the reply came from (it assumes it's from the server it just contacted).
This flow perfectly mirrors the "postcard" analogy: create a message, address it to the server, send it, and then wait for a postcard in return.
Conclusion
You have now surveyed the landscape of UDP socket programming. By contrasting it with your existing knowledge of TCP, the unique, connectionless nature of UDP becomes much clearer.
Key Takeaways:
- UDP is connectionless: There is no
connect(),listen(), oraccept()to establish a session. - Sockets are
SOCK_DGRAM: This type is specified in thesocket()call to use the UDP protocol. - Communication uses
sendto()andrecvfrom(): These functions are essential because address information for the destination (insendto) or source (inrecvfrom) must be handled with every packet. - Server
bind()is mandatory: A UDP server mustbind()to a well-known port to be discoverable by clients. - Client
bind()is optional: A UDP client typically lets the OS assign an ephemeral port on the firstsendto()call.
Preview of the Next Lesson:
Theory is one thing, but practice is another. Now that you have a solid conceptual map of the UDP API, you're ready for the next step. In our next lesson, you will implement a simple UDP echo client-server program in C. You'll write the code for the functions we've discussed today and see your own UDP application come to life.