docs: @Override
      public void run() {
          try {
              log.info("UDP - client started: " + this.hostname + ":" + this.port);
              isRunning = true;
              buf       = new ByteBuffer(5000);
              buf.setString(getInitMessage());    // A buffer size of 5000 to handle the server_param message.
              socket = new DatagramSocket();
  
              // Timeout of 3mins to ensure that the coach stays connected.
              socket.setSoTimeout(300000);
              DatagramPacket p = new DatagramPacket(buf.getByteArray(), buf.getByteArray().length,
                                     InetAddress.getByName(hostname), port);
              socket.send(p);
              socket.receive(p);
              this.host = p.getAddress();
              this.port = p.getPort();
              received(buf.getString());
  
              // Continue until the program is closed. This is where sserver messages are received.
              while (isRunning) {
                  buf.reset();
                  DatagramPacket packet = new DatagramPacket(buf.getByteArray(), buf.getByteArray().length);
                  socket.receive(packet);
                  received(buf.getString());
              }
          } catch (Exception ex) {
              log.error("Stopped running " + getName() + " " + getDescription() + " because: " + ex.toString());
          }
  
          // Clean up.
          socket.close();
          try {
              buf.close();
          } catch (IOException ex) {
              log.error("Error cleaning up thread - " + ex.getMessage());
          }
          try {
              this.finalize();
          } catch (Throwable ex) {
              log.error("Error cleaning up thread - " + ex.getMessage());
          }
          log.info("UDP - client terminated: " + this.hostname + ":" + this.port);
      }