socket = new DatagramSocket();
try {
    DatagramPacket dg = new DatagramPacket("hey", 3, InetAddress.getByName("localhost"), 5555);
    socket.send(dg);
    byte[] buffer = new byte[65536];
    DatagramPacket dg2 = new DatagramPacket(buffer, buffer.length);
    socket.receive(dg2);
    System.out.println(new String(buffer).equals("yo"));
} finally {
    socket.close();
}

Since the client and server both use a DatagramPacket internally of
length 65536, this works well when the data is short and similar between the
request and response. Is a solution such as some sort of
Socket.setSoTimeout things possible?

One other solution is to bind the packet to a NetworkInterface
instance:

String host = "ladida";
packet.setSocketAddress(new InetSocketAddress(InetAddress.getByName(host), 0));
socket.send(packet);

And then on the other side of the world you select the
non-global socket address:

String host = "foobar";
packet.setSocketAddress(new InetSocketAddress(InetAddress.getByName(host), 0));
socket.send(packet);

Thus bypassing the need to bind the packet, but still doing selective
sending without a queueing mechanism.



/* The following implements a server-connector which processes the
stages in the request-response cycle:

 1. Stage 1. CREATE THE SOCKET.
 2. Stage 2. BIND THE SOCKET.
 3. Stage 3. LISTEN FOR HTTP REQUESTS.
 4. Stage 4. FOR EACH REQUEST RECEIVED, SEND RESPONSES UNTIL PACKET IS FULL
           OR RESPONSE IS FINISHED.

 The following is the abstract form of a generic request and response
object, each of which will contain both the bytes and the listeners
you put in place afterwards to process the data:

    public abstract class Request
    {
      public abstract void reset();
      public abstract String getParameter(String key);
      public int getVersionCode();
      public String getCommand();
      public String getFile();
      public String getServerName();
      public String getContentType();
      public int getContentLength();
      public String getCurrentLine();
      public int getLineCount();
      public boolean isResponse()
      {
         return false;
      }
    }
    public abstract class Response
    {
      public abstract void reset();
      public abstract String getHeaderValue(String key);
      public String getDocument();
      public String getVersionCode();
      public String getCommand();
      public String getFile();
      public int getConnectionCount();
      public String getContentType();
      public int getContentLength();
      public String getCurrentLine();
      public int getLineCount();
      public boolean isResponse()
      {
         return true;
      }
    }

 The server will send a very simple non-persistent response with the
data "yo" as the response, and then anything it receives is considered
data on that request as of an initial block ready to copy just as if
"hey" was requested and "yo" was returned. All other data is held for
the queued listeners if the request is a response packet.

 There are therefore two main states for the request process requirement:
 1. The server is sending data chunks as ACKs (req/resp)
 2. The server is sending data chunks not as ACKs (clien/resp).

 The code below implements MinimalAsyncSocket.
 It expects a single listener to implement its output and input,
and to call its methods:
 1. output(requestBuffer, request)}    the byte sequence in request along with the current
                                       request which is the request for the socket or the
                                       response for the last send.
 2. getAck(requestBuffer)}             the person who posted the request for the input or
                                       the data for the output.
 3. getResponse(requestBuffer)}        if this is the one person calling this we wait for
                                       the socket to get ready to write and reset the input
                                       buffer.
 4. sendCRLF(requestBuffer)            The last line has been sent completely the output can
                                       now start to send data on the input.

 Note that the above has a state machince. The Protocol.State is where we
 will stop when processing a state response by getting responses and
 posting a completion in turn. In this way we can have asynchronous
progress.


// Jonathan Scott is not a hacker