AIM: ECHO DATAGRAM (UDP)
A DatagramSocket provides an unreliable, connectionless, datagram connection (that is, a UDP/IP socket connection).
Unlike the reliable connection provided by a Socket, there is no guarantee that what you send over a UDP connection actually gets to the receiver. The TCP connection provided by the Socket class takes care retransmitting any packets that might get lost. Packets sent through UDP simply are sent out and forgotten, which means that if you need to know that the receiver got the data, you will have to send back some sort of acknowledgment. This does not mean that your data will never get to the other end of a UDP connection. If a network error happens (your cat jiggles the Ethernet plug out of the wall, for instance) then the UDP layer will not try to send it again or even know that the packet did not get to the recipient.
Connectionless means that the socket does not have a fixed receiver. You may use the same DatagramSocket to send packets to different hosts and ports, whereas a Socket connection is only to a given host and port. Once a Socket is connected to a destination it cannot be changed. The fact that UDP sockets are not bound to a specific destination also means that the same socket can listen for packets as well as originating them. There is no UDP DatagramServerSocket equivalent to the TCP ServerSocket.
Datagram refers to the fact that the information is sent as discrete packets rather than a continuous ordered stream. The individual packet boundaries are preserved. It might help to think of it as dropping fixed-size postcards in a mailbox. For example, if you send four packets, the order in which they arrive at the destination is not guaranteed to be the same in which they were sent. The receiver could get them in the same order they were sent or they could arrive in reverse order. In any case, each packet will be received whole.
Given the above constraints, why would anyone want to use a DatagramSocket? There are several advantages to using UDP, as follows:
- You need to communicate with several different hosts. Because a DatagramSocket is not bound to a particular host, you may use the same object to communicate with different hosts by specifying the InetAddress when you create each DatagramPacket.
- You are not worried about reliable delivery. If the application you are writing does not need to know that the data it sends get to the other end, using a UDP socket eliminates the overhead of acknowledging each packet that TCP does. Another case would be if the protocol you are using has its own method of handling reliable delivery and retransmission.
- The amount of data being sent does not merit the overhead of setting up a connection and the reliable delivery mechanism. An application that is only sending 100 bytes for each transaction every 10 minutes would be an example of this situation.
The NFS (Network File System) protocol version two, originally developed by Sun with implementations available for most operating systems, is an example application that uses UDP for its transport mechanism. Another example of an application where a DatagramSocket might be appropriate would be a multiplayer game. The central server would need to communicate to all of the players involved, and would not necessarily need to know that a position update got to the player.
Unlike the client and server portions of connection-oriented classes, the datagram versions of the client and server behave in nearly identical manners-the only difference occurs in implementation. For the datagram model, the same class is used for both client and server halves. The following lines create client and server datagram sockets:
DatagramSocket serverSocket = new DatagramSocket( 4545 );
DatagramSocket clientSocket = new DatagramSocket();
The server specifies its port using the lone constructor parameter 4545. Because the client calls the server, the client can use any available port. The omitted constructor parameter in the second call instructs the operating system to assign the next available port number. The client could have requested a specific port, but the call would fail if some other socket had already bound itself to that port. It's better not to specify a port unless the intent is to be a server.