Receive a message from the other end.  Returns a tuple of the
        command (a string) and payload (a list).

def recv(self):
        """
        Receive a message from the other end.  Returns a tuple of the
        command (a string) and payload (a list).
        """

        # See if we have a message to process...
        if self._recvbuf:
            return self._recvbuf_pop()

        # If it's closed, don't try to read more data
        if not self._sock:
            raise ConnectionClosed("Connection closed")

        # OK, get some data from the socket
        while True:
            try:
                data = self._sock.recv(4096)
            except socket.error:
                # We'll need to re-raise
                e_type, e_value, e_tb = sys.exc_info()

                # Make sure the socket is closed
                self.close()

                # Re-raise
                raise e_type, e_value, e_tb

            # Did the connection get closed?
            if not data:
                # There can never be anything in the buffer here
                self.close()
                raise ConnectionClosed("Connection closed")

            # Begin parsing the read-in data
            partial = self._recvbuf_partial + data
            self._recvbuf_partial = ''
            while partial:
                msg, sep, partial = partial.partition('\n')

                # If we have no sep, then it's not a complete message,
                # and the remainder is in msg
                if not sep:
                    self._recvbuf_partial = msg
                    break

                # Parse the message
                try:
                    self._recvbuf.append(json.loads(msg))
                except ValueError as exc:
                    # Error parsing the message; save the exception,
                    # which we will re-raise
                    self._recvbuf.append(exc)

            # Make sure we have a message to return
            if self._recvbuf:
                return self._recvbuf_pop()