Executes when UDP data has been received and sends the packet data
        to our app to process the request.

        Args:
          data (str): The raw serialized packet data received.
          address (tuple): The address and port of the origin of the received
            packet. E.g. (address, port).

        Returns:
          None

def receive_datagram(self, data, address):
        """Executes when UDP data has been received and sends the packet data
        to our app to process the request.

        Args:
          data (str): The raw serialized packet data received.
          address (tuple): The address and port of the origin of the received
            packet. E.g. (address, port).

        Returns:
          None

        """

        # If we do not specify an application, just print the data.
        if not self.app:
            logger.debug("Packet received", address, data)
            return False

        # Send the data we've recieved from the network and send it
        # to our application for processing.
        try:
            response = self.app.handle_message(data, address)
        except Exception as err:
            logger.error("Error processing message from " + str(address) +
                          ":" + str(data))
            logger.error(traceback.format_exc())
            return False

        # If our application generated a response to this message,
        # send it to the original sender.
        if response:
            self.send_datagram(response, address)