- Forward


UDP Socket Programming
An Introduction with Examples in C


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Review
Back SMYC Forward
  • UDP:
    • Not connection-orieneted
    • Message-oriented
    • Unreliabale
  • Internet Programming Basics:
    • Byte order
    • Addresses and ports
UDP Programming
Back SMYC Forward
  • Both Parties:
    • socket() socket
  • The Receiving Party:
    • bind() bind
    • recvfrom() recvfrom
  • The Sending Party:
    • sendto() sendto
Creating a Socket: socket() socket
Back SMYC Forward
int socket(int domain, int type, int protocol)
Purpose:
Create a socket
Details:
domain AF_INET or AF_INET6 for IP
type SOCK_DGRAM for UDP
protocol 0 for UDP over IP
Return The file descriptor on success; -1 on error
#include <sys/socket.h> sys/socket.h
Setting-Up for Receiving
Back SMYC Forward
  • Conceptually:
    • The socket can be bound to any IP address on the host
    • The socket must be bound to a particular port so that it can be "advertised"
  • Initializing the sockaddr:
    • struct sockaddr_in address; memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = htons(WELL_KNOWN_PORT); // For this service address.sin_addr.s_addr = htonl(INADDR_ANY);
Binding to an Address and/or Port: bind() bind
Back SMYC Forward
int bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
Purpose:
Associate a socket with a particular address and/or port
Details:
fd The file descriptor of a socket
addr The address/port to bind to
addrlen The length of the address
Return 0 on success; -1 on error
#include <sys/socket.h> sys/socket.h
Receiving a Datagram: recvfrom() recvfrom
Back SMYC Forward
ssize_t recvfrom(int fd, void *buffer, size_t buflen, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
Purpose:
Receive a UDP datagram
Details:
fd The file descriptor of the UDP socket
buffer The buffer to fill with the datagram's payload
length The length of the buffer
flags Flags (often 0)
src_addr The address the datagram was sent from
addrlen The length of the source's address
Return The number of bytes received on success; -1 on error
#include <sys/socket.h> sys/socket.h
A Simple Sequential Text "Receiver"
Back SMYC Forward
unixexamples/udp/weather_recorder.c
 
A Simple Sequential Text "Receiver" (cont.)
Back SMYC Forward
  • A Conceptual Question:
    • Is this "receiver" a client, a server, or neither?
  • An Answer and Explanation:
    • Because its role is to wait for and respond to a request (i.e., to record data), it is a server
      Expand
Setting-Up for Sending
Back SMYC Forward
  • Conceptually:
    • The datagram can be sent from any address/port so the socket needn't be bound
    • The datagram must be sent to a particular address/port (so that information will have to be passed to the function that does the sending)
  • Initializing the Destination sockaddr:
    • struct sockaddr_in destination; memset(&destination, 0, sizeof(struct sockaddr_in)); destination.sin_family = AF_INET; inet_pton(AF_INET, RECEIVER_ADDRESS, &(destination.sin_addr)); destination.sin_port = htons(RECEIVER_PORT);
Sending a Datagram: sendto() sendto
Back SMYC Forward
ssize_t sendto(int fd, const void *buffer, size_t buflen, int flags, const struct sockaddr *dest_addr, socklen_t *addrlen)
Purpose:
Send a UDP datagram to a particular address and port
Details:
fd The file descriptor of the UDP socket
buffer The datagram's payload
length The length of the payload
flags Flags (often 0)
dest_addr The address to send the datagram to
addrlen The length of the destination address
Return The number of bytes sent on success; -1 on error
#include <sys/socket.h> sys/socket.h
A Simple Text "Sender"
Back SMYC Forward
unixexamples/udp/weather_station.c
 
Sending/Receiving and Clients/Servers
Back SMYC Forward
  • A Conceptuial Question:
    • Are all "senders" clients and all "receivers" servers?
  • An Answer and Explanation:
    • No! In fact, both clients and servers often both send and receive.
      Expand
A Server that Receives and Sends
Back SMYC Forward
  • An Observation:
    • In the example above, all communication is one-way
  • A Different Example:
    • The client requests a forecast for a particular location (using UDP) and the server responds (again using UDP)
A Server that Receives and Sends (cont.)
Back SMYC Forward
unixexamples/udp/forecast_server.c
 
A Client that Sends and Receives
Back SMYC Forward
unixexamples/udp/forecast_client.c
 
Message Formats
Back SMYC Forward
  • An Observation:
    • In the examples above, all of the messages contain text
  • The Rationale:
    • The byte order doesn't matter and text is always represented using ASCII or Unicode
  • An Alternative:
    • Use common binary representations and network byte order
A struct for a Binary Message
Back SMYC Forward
unixexamples/udp/weather.h
 
A Server with a Binary Message
Back SMYC Forward
unixexamples/udp/range_server.c
 
A Client with a Binary Message
Back SMYC Forward
unixexamples/udp/range_client.c
 
Sequential and Concurrent Servers
Back SMYC Forward
  • A Question You Should Have Asked:
    • What happens if a server receives a request while it is processing another request?
  • The Answer:
    • The request is buffered
Sequential and Concurrent Servers (cont.)
Back SMYC Forward
  • The Implication:
    • The server only handles one request "at a time"
  • Using Concurrent Processing to Handle Multiple Requests:
    • Use multiple processes
    • Use multiple threads
A Server with Multiple Processes
Back SMYC Forward
unixexamples/udp/multiprocessed_forecast_server.c
 
A Server with Multiple Threads
Back SMYC Forward
unixexamples/udp/threaded_forecast_server.c
 
Improving Concurrent Servers
Back SMYC Forward
  • Pre-Forking:
    • Instead of child processes when needed, create them at start-up (and place them in a pool)
    • Connections are placed in a queue
    • When a child process is done with a connection it doesn't terminate; instead it retrieves the next connection in the queue
  • Pre-Threading:
    • The same idea, but using threads instead of processes
Socket Options: setsockopt() setsockopt
Back SMYC Forward
int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
Purpose:
Set socket options
Details:
fd The file descriptor of the UDP socket
level SOL_SOCKET, IPPROTO_IP, ...
optname The option to set
optval The value of the option
optlen The size of the optval argument
Return 0 on success; -1 on error
#include <sys/socket.h> sys/socket.h
Socket Options (cont.)
Back SMYC Forward
  • Transaction-Related UDP Option Names:
    • SO_SNDTIMEO and SO_RCVTIMEO allow you to set timeouts (i.e., how long a call will block before failing)
    • SO_LINGER allows the socket to delay closing if there are data to send
  • Setup-Related UDP Option Names:
    • SO_REUSEADDR and SO_REUSEPORT allow you to re-use an address and/or port even if they are already bound (which can be useful when a server fails and must be restarted)
    • SO_RCVBUF and SO_SNDBUF allow you to change buffer sizes
Socket Options (cont.)
Back SMYC Forward
A Partial Example
struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval));
There's Always More to Learn
Back -