docs: def call(self, args=None, kwargs=None, node=None, send_timeout=1000, recv_timeout=5000, zmq_ctx=None):
          """
          Calls a service on a node with req as arguments. if node is None, a node is chosen by zmq.
          if zmq_ctx is passed, it will use the existing context
          Uses a REQ socket. Ref : http://api.zeromq.org/2-1:zmq-socket
          :param node : the node name
  
          """
  
          context = zmq_ctx or zmq.Context()
          assert isinstance(context, zmq.Context)
  
          args = args or ()
          assert isinstance(args, tuple)
          kwargs = kwargs or {}
          assert isinstance(kwargs, dict)
  
          socket = context.socket(zmq.REQ)
  
          # connect to all addresses ( optionally matching node name )
          for n, a in [(n, a) for (n, a) in self.providers if (not node or n == node)]:
              socket.connect(a)
  
          # build message
          fullreq = ServiceRequest(service=self.name, args=pickle.dumps(args), kwargs=pickle.dumps(kwargs))
  
          poller = zmq.Poller()
          poller.register(socket)  # POLLIN for recv, POLLOUT for send
  
          evts = dict(poller.poll(send_timeout))
          if socket in evts and evts[socket] == zmq.POLLOUT:
              socket.send(fullreq.serialize())
              # TODO : find a way to get rid fo these timeouts when debugging
              # TODO : when timeout Exception should occur ( not returning None )
              evts = dict(poller.poll(recv_timeout))  # blocking until answer
              if socket in evts and evts[socket] == zmq.POLLIN:
                  resp = socket.recv()
                  fullresp = ServiceResponse_dictparse(resp)
  
                  if fullresp.has_field('response'):
                      return pickle.loads(fullresp.response)
                  elif fullresp.has_field('exception'):
                      svcexc = fullresp.exception  # This has already been parsed by ServiceResponse_dictparse
                      tb = pickle.loads(svcexc.traceback)
                      if Traceback and isinstance(tb, Traceback):
                          reraise(pickle.loads(svcexc.exc_type), pickle.loads(svcexc.exc_value), tb.as_traceback())
                      else:  # traceback not usable
                          reraise(pickle.loads(svcexc.exc_type), pickle.loads(svcexc.exc_value), None)
                  else:
                      raise UnknownResponseTypeException("Unknown Response Type {0}".format(type(fullresp)))
              else:
                  raise ServiceCallTimeout("Did not receive response through ZMQ socket.")
          else:
              raise ServiceCallTimeout("Can not send request through ZMQ socket.")