docs: def start_server(data_stream, port=5557, hwm=10):
      """Start a data processing server.
  
      This command starts a server in the current process that performs the
      actual data processing (by retrieving data from the given data stream).
      It also starts a second process, the broker, which mediates between the
      server and the client. The broker also keeps a buffer of batches in
      memory.
  
      Parameters
      ----------
      data_stream : :class:`.DataStream`
          The data stream to return examples from.
      port : int, optional
          The port the server and the client (training loop) will use to
          communicate. Defaults to 5557.
      hwm : int, optional
          The `ZeroMQ high-water mark (HWM)
          <http://zguide.zeromq.org/page:all#High-Water-Marks>`_ on the
          sending socket. Increasing this increases the buffer, which can be
          useful if your data preprocessing times are very random.  However,
          it will increase memory usage. There is no easy way to tell how
          many batches will actually be queued with a particular HWM.
          Defaults to 10. Be sure to set the corresponding HWM on the
          receiving end as well.
  
      """
      logging.basicConfig(level='INFO')
  
      context = zmq.Context()
      socket = context.socket(zmq.PUSH)
      socket.set_hwm(hwm)
      socket.bind('tcp://*:{}'.format(port))
  
      it = data_stream.get_epoch_iterator()
  
      logger.info('server started')
      while True:
          try:
              data = next(it)
              stop = False
              logger.debug("sending {} arrays".format(len(data)))
          except StopIteration:
              it = data_stream.get_epoch_iterator()
              data = None
              stop = True
              logger.debug("sending StopIteration")
          send_arrays(socket, data, stop=stop)