public static function blockingRead($socket, $timeout = 500.0)
    {
        static $cmds = array();

        $tv_sec = floor(($timeout % 1000));
        $tv_usec = ($timeout * 1000);

        $start = microtime(true);
        while (count($cmds) == 0) {
            if (((microtime(true) - $start) * 1000) > $timeout) {
                throw new Exception('Blocking read timed out');
            }

            $write = null;
            $except = null;
            $read = array($socket);

            socket_select($read, $write, $except, $tv_sec, $tv_usec);
            foreach ($read as $s) {
                $cmds[] = self::read($s);
            }
        }

        return array_shift($cmds);
    }