/**
  * Receives a datagram packet from this socket. When this method returns, the
  * <tt>DatagramPacket</tt>'s buffer is filled with the data received. The datagram packet also
  * contains the sender's IP address, and the port number on the sender's machine.
  *
  * <p>This method blocks until a datagram is received. The <tt>length</tt> field of the datagram
  * packet object contains the length of the received message. If the message is longer than the
  * packet's length, the message is truncated.
  *
  * @param p the <tt>DatagramPacket</tt> into which to place the incoming data
  * @throws IOException if an I/O error occurs
  * @see DatagramSocket#receive(DatagramPacket)
  */
 @Override
 public void receive(DatagramPacket p) throws IOException {
   synchronized (inReceiveSyncRoot) {
     inReceive++;
   }
   try {
     super.receive(p);
   } finally {
     synchronized (inReceiveSyncRoot) {
       inReceive--;
       inReceiveSyncRoot.notifyAll();
     }
   }
 }
  /**
   * Closes this datagram socket.
   *
   * <p>Any thread currently blocked in {@link #receive} upon this socket will throw a {@link
   * SocketException} and this datagram socket will wait for it to return.
   *
   * @see DatagramSocket#close()
   */
  @Override
  public void close() {
    super.close();

    if (inReceiveSyncRoot == null) return;

    synchronized (inReceiveSyncRoot) {
      boolean interrupted = false;

      while (inReceive > 0)
        try {
          inReceiveSyncRoot.wait();
        } catch (InterruptedException iex) {
          interrupted = true;
        }
      if (interrupted) Thread.currentThread().interrupt();
    }
  }