function publish($topic, $message, $qos, $retain = 0)
    {
        // Do nothing, if socket isn't connected
        if(!$this->socket) {
            $this->debugMessage("Packet NOT sent, socket not connected! (QoS: ".$qos." ; topic: ".$topic." ; msg: ".$message.")",2);
            return false;
        }

        // Sanity checks for QoS and retain values
        if( ( $qos != 0 && $qos != 1 ) || ($retain != 0 && $retain != 1 ) ) {
            $this->debugMessage("Packet NOT sent, invalid qos/retain value (QoS: ".$qos." ; topic: ".$topic." ; msg: ".$message.")",2);
            return false;
        }

        //
        $bytes = 0;
        $payload = $this->convertString($topic,$bytes);

        // Add message identifier to QoS (1/2) packages
        if($qos > 0 ) {
            $payload .= chr($this->packet >> 8) . chr($this->packet & 0xff);
            $bytes+=2;
        }

        // Add Message to package and create header
        $payload .= $message;
        $bytes += strlen($message);
        $header = $this->createHeader( 0x30 + ($qos<<1) + $retain , $bytes );

        //
        fwrite($this->socket, $header, strlen($header));
        fwrite($this->socket, $payload, $bytes);

        // If message QoS = 1 , add message to queue
        if($qos==1) {
            $this->messageQueue[ $this->packet ] = [
                "topic" => $topic,
                "message" => $message,
                "qos" => $qos,
                "retain" => $retain,
                "time" => time(),
                "attempt" => 1
            ];
        }

        //
        $this->debugMessage("Packet sent (QoS: ".$qos." ; topic: ".$topic." ; bytes: ".$bytes." ; msg: ".$message.")",2);

        //
        $this->packet++;
        return true;
    }