def _udp_transact(self, payload, handler, *args,<EOL>broadcast=False, timeout=TIMEOUT):
if self.host in _BUFFER:<EOL><INDENT>del _BUFFER[self.host]<EOL><DEDENT>host = self.host<EOL>if broadcast:<EOL><INDENT>host = '<STR_LIT>'<EOL><DEDENT>retval = None<EOL>for _ in range(RETRIES):<EOL><INDENT>_SOCKET.sendto(bytearray(payload), (host, PORT))<EOL>start = time.time()<EOL>while time.time() < start + timeout:<EOL><INDENT>data = _BUFFER.get(self.host, None)<EOL>if data:<EOL><INDENT>retval = handler(data, *args)<EOL><DEDENT>if retval:<EOL><INDENT>return retval<EOL><DEDENT><DEDENT><DEDENT>
Complete a UDP transaction.

        UDP is stateless and not guaranteed, so we have to
        take some mitigation steps:
        - Send payload multiple times.
        - Wait for awhile to receive response.

        :param payload: Payload to send.
        :param handler: Response handler.
        :param args: Arguments to pass to response handler.
        :param broadcast: Send a broadcast instead.
        :param timeout: Timeout in seconds.