'Send a message to MongoDB and return a Response.
:Parameters:
- `operation`: a _Query or _GetMore object.
- `read_preference` (optional): A ReadPreference.
- `exhaust` (optional): If True, the socket used stays checked out.
It is returned along with its Pool in the Response.
- `address` (optional): Optional address when sending a message
to a specific server, used for getMore.'

def _send_message_with_response(self, operation, read_preference=None, exhaust=False, address=None):

    with self.__lock:
        self._kill_cursors_executor.open()
    topology = self._get_topology()
    if address:
        server = topology.select_server_by_address(address)
        if (not server):
            raise AutoReconnect(('server    %s:%d    no    longer    available' % address))
    else:
        selector = (read_preference or writable_server_selector)
        server = topology.select_server(selector)
    set_slave_ok = ((topology.description.topology_type == TOPOLOGY_TYPE.Single) and (server.description.server_type != SERVER_TYPE.Mongos))
    return self._reset_on_error(server, server.send_message_with_response, operation, set_slave_ok, self.__all_credentials, self._event_listeners, exhaust)
