Datagram Sockets
A datagram socket provides a symmetric data exchange interface without requiring connection establishment. Each message carries the destination address. The following figure shows the flow of communication between server and client.
The bind
()
step for the server is optional.
Connectionless Communication Using Datagram Sockets

Create datagram sockets as described in Socket Creation. If a particular local address is needed, the
bind
()
operation must precede the first data transmission.
Otherwise, the system sets the local address or port when data is first sent. Use
sendto
()
to send data. For more information, see the
bind
(3C) and
sendto
(3C) man pages.
sendto(s, buf, buflen, flags, (struct sockaddr *) &to, tolen);
The s, buf,
buflen, and flags parameters
are the same as in connection-oriented sockets. The to and
tolen values indicate the address of the intended
recipient of the message. A locally detected error condition, such as an unreachable
network, causes a return of -1
and
errno to be set to the error number.
recvfrom(s, buf, buflen, flags, (struct sockaddr *) &from, &fromlen);
To receive messages on a datagram socket,
recvfrom
()
is used. Before the call,
fromlen is set to the size of the
from buffer. On return,
fromlen
is set to the size of the address from which
the datagram was received. For more information, see the
recvfrom
(3C) man page.
Datagram sockets can also use the connect
()
call to associate a socket with a specific destination address. The socket
can then use the send
()
call. Any data that is sent on
the socket that does not explicitly specify a destination address is
addressed to the connected peer. Only the data that is received from that
peer is delivered. A socket can have only one connected address at a time.
A second connect
()
call changes the destination address.
Connect requests on datagram sockets return immediately. The system
records the peer's address. Neither accept
()
nor
listen
()
are used with datagram sockets. For more
information, see the
send
(3C),
connect
(3C),
accept
(3C), and
listen
(3C) man pages.
A datagram socket can return errors from previous send
()
calls
asynchronously while the socket is connected. The socket can report these errors on
subsequent socket operations. Alternately, the socket can use an option of
getsockopt
(), SO_ERROR
to interrogate the error
status. For more information, see the
getsockopt
(3C) man page.
The following example code shows how to send an Internet call by creating a socket, binding a name to the socket, and sending the message to the socket.
Example 7-5 Sending an Internet Family Datagram
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #define DATA "The sea is calm, the tide is full . . ." /* * Here I send a datagram to a receiver whose name I get from * the command line arguments. The form of the command line is: * dgramsend hostname portnumber */ main(int argc, char *argv[]) { int sock, errnum; struct sockaddr_in6 name; struct hostent *hp; /* Create socket on which to send. */ sock = socket(AF_INET6,SOCK_DGRAM, 0); if (sock == -1) { perror("opening datagram socket"); exit(1); } /* * Construct name, with no wildcards, of the socket to ``send'' * to. getinodebyname returns a structure including the network * address of the specified host. The port number is taken from * the command line. */ hp = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT, &errnum); if (hp == (struct hostent *) 0) { fprintf(stderr, "%s: unknown host\n", argv[1]); exit(2); } bzero (&name, sizeof (name)); memcpy((char *) &name.sin6_addr, (char *) hp->h_addr, hp->h_length); name.sin6_family = AF_INET6; name.sin6_port = htons(atoi(argv[2])); /* Send message. */ if (sendto(sock, DATA, sizeof DATA, 0, (struct sockaddr *) &name,sizeof name) == -1) perror("sending datagram message"); close(sock); exit(0); }
The following sample code shows how to read an Internet call by creating a socket, binding a name to the socket, and then reading from the socket.
Example 7-6 Reading Internet Family Datagrams
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> /* * This program creates a datagram socket, binds a name to it, then * reads from the socket. */ main() { int sock, length; struct sockaddr_in6 name; char buf[1024]; /* Create socket from which to read. */ sock = socket(AF_INET6, SOCK_DGRAM, 0); if (sock == -1) { perror("opening datagram socket"); exit(1); } /* Create name with wildcards. */ bzero (&name, sizeof (name)); name.sin6_family = AF_INET6; name.sin6_addr = in6addr_any; name.sin6_port = 0; if (bind (sock, (struct sockaddr *)&name, sizeof (name)) == -1) { perror("binding datagram socket"); exit(1); } /* Find assigned port value and print it out. */ length = sizeof(name); if (getsockname(sock,(struct sockaddr *) &name, &length) == -1) { perror("getting socket name"); exit(1); } printf("Socket port #%d\n", ntohs(name.sin6_port)); /* Read from the socket. */ if (read(sock, buf, 1024) == -1 ) perror("receiving datagram packet"); /* Assumes the data is printable */ printf("-->%s\n", buf); close(sock); exit(0); }