The server and client programs that use UDP are almost identical to their TCP counterparts; only the protocol has changed. As before, it does matter which side starts first. The receiving side blocks and waits for the sender. In this case, the receiver/client has to be started first:
# Server BEGIN { print strftime() |& "/inet/udp/8888/0/0" close("/inet/udp/8888/0/0") }
The receiver is almost identical to the TCP receiver:
# Client BEGIN { print "hi!" |& "/inet/udp/0/localhost/8888" "/inet/udp/0/localhost/8888" |& getline print $0 close("/inet/udp/0/localhost/8888") }
In the case of UDP, the initial print
command is the one
that actually sends data so that there is a connection.
UDP and “connection” sounds strange to anyone
who has learned that UDP is a connectionless protocol.
Here, “connection” means that the connect()
system call
has completed its work and completed the “association”
between a certain socket and an IP address. Thus there are
subtle differences between connect()
for TCP and UDP;
see the man page for details.5
UDP cannot guarantee that the datagrams at the receiving end will arrive in exactly the same order they were sent. Some datagrams could be lost, some doubled, and some could arrive out of order. But no overhead is necessary to accomplish this. This unreliable behavior is good enough for tasks such as data acquisition, logging, and even stateless services like the original versions of NFS.
This subtlety
is just one of many details that are hidden in the socket
API, invisible and intractable for the gawk
user.
The developers are currently considering how to rework the
network facilities to make them easier to understand and use.