def start_server(self):
        sock = self.ctx.socket(zmq.REP)
        sock.setsockopt(zmq.LINGER, 0)
        port = sock.bind_to_random_port("tcp://0.0.0.0")
        server_addr = 'tcp://%s:%d' % (self.host, port)
        guide_sock = self.ctx.socket(zmq.REQ)
        guide_sock.setsockopt(zmq.LINGER, 0)
        guide_sock.connect(self.guide_addr)

        def run():
            logger.debug("server started at %s", server_addr)

            while self._started:
                if not sock.poll(1000, zmq.POLLIN):
                    continue
                type_, msg = sock.recv_pyobj()
                logger.debug('server recv: %s %s', type_, msg)
                if type_ == SERVER_STOP:
                    sock.send_pyobj(None)
                    break
                elif type_ == SERVER_FETCH:
                    uuid, indices, client_addr = msg
                    if uuid in self.master_broadcast_blocks:
                        block_num = len(self.master_broadcast_blocks[uuid])
                        bls = []
                        for index in indices:
                            if index >= block_num:
                                logger.warning('input index too big %s for '
                                               'len of blocks  %d from host %s',
                                               str(indices), block_num, client_addr)
                                sock.send_pyobj((SERVER_FETCH_FAIL, None))
                            else:
                                bls.append(self.master_broadcast_blocks[uuid][index])
                        sock.send_pyobj((SERVER_FETCH_OK, (indices, bls)))
                    elif uuid in self.uuid_state_dict:
                        fd = os.open(self.uuid_state_dict[uuid][0], os.O_RDONLY)
                        mmfp = mmap.mmap(fd, 0, access=ACCESS_READ)
                        os.close(fd)
                        bitmap = self.uuid_map_dict[uuid]
                        block_num = len(bitmap)
                        bls = []
                        for index in indices:
                            if index >= block_num:
                                logger.warning('input index too big %s for '
                                               'len of blocks  %d from host %s',
                                               str(indices), block_num, client_addr)
                                sock.send_pyobj((SERVER_FETCH_FAIL, None))
                            else:
                                mmfp.seek(bitmap[index][0])
                                block = mmfp.read(bitmap[index][1])
                                bls.append(block)
                        mmfp.close()
                        sock.send_pyobj((SERVER_FETCH_OK, (indices, bls)))
                    else:
                        logger.warning('server fetch failed for uuid %s '
                                       'not exists in server %s from host %s',
                                       uuid, socket.gethostname(), client_addr)
                        sock.send_pyobj((SERVER_FETCH_FAIL, None))
                elif type_ == DATA_GET:
                    uuid, compressed_size = msg
                    if uuid not in self.uuid_state_dict or not self.uuid_state_dict[uuid][1]:
                        if uuid not in self.download_threads:
                            sources = self._get_sources(uuid, guide_sock)
                            if not sources:
                                logger.warning('get sources from guide server failed in host %s',
                                               socket.gethostname())
                                sock.send_pyobj(DATA_GET_FAIL)
                                continue
                            self.download_threads[uuid] = spawn(self._download_blocks,
                                                                *[sources, uuid, compressed_size])
                            sock.send_pyobj(DATA_DOWNLOADING)
                        else:
                            sock.send_pyobj(DATA_DOWNLOADING)
                    else:
                        sock.send_pyobj(DATA_GET_OK)
                elif type_ == SERVER_CLEAR_ITEM:
                    uuid = msg
                    self.clear(uuid)
                    sock.send_pyobj(None)
                else:
                    logger.error('Unknown server message: %s %s', type_, msg)
                    sock.send_pyobj(None)

            sock.close()
            logger.debug("stop Broadcast server %s", server_addr)
            for uuid in list(self.uuid_state_dict.keys()):
                self.clear(uuid)

        return server_addr, spawn(run)