def BuildExcerpts (self, docs, index, words, opts=None):
		"""
		Connect to searchd server and generate exceprts from given documents.
		"""
		if not opts:
			opts = {}

		assert(isinstance(docs, list))
		assert(isinstance(index, (str,text_type)))
		assert(isinstance(words, (str,text_type)))
		assert(isinstance(opts, dict))

		sock = self._Connect()

		if not sock:
			return None

		# fixup options
		opts.setdefault('before_match', '<b>')
		opts.setdefault('after_match', '</b>')
		opts.setdefault('chunk_separator', ' ... ')
		opts.setdefault('html_strip_mode', 'index')
		opts.setdefault('limit', 256)
		opts.setdefault('limit_passages', 0)
		opts.setdefault('limit_words', 0)
		opts.setdefault('around', 5)
		opts.setdefault('start_passage_id', 1)
		opts.setdefault('passage_boundary', 'none')

		# build request
		# v.1.0 req

		flags = 1 # (remove spaces)
		if opts.get('exact_phrase'):	flags |= 2
		if opts.get('single_passage'):	flags |= 4
		if opts.get('use_boundaries'):	flags |= 8
		if opts.get('weight_order'):	flags |= 16
		if opts.get('query_mode'):		flags |= 32
		if opts.get('force_all_words'):	flags |= 64
		if opts.get('load_files'):		flags |= 128
		if opts.get('allow_empty'):		flags |= 256
		if opts.get('emit_zones'):		flags |= 512
		if opts.get('load_files_scattered'):	flags |= 1024
		
		# mode=0, flags
		req = bytearray()
		req.extend(pack('>2L', 0, flags))

		# req index
		index = str_bytes(index)
		req.extend(pack('>L', len(index)))
		req.extend(index)

		# req words
		words = str_bytes(words)
		req.extend(pack('>L', len(words)))
		req.extend(words)

		# options
		opts_before_match = str_bytes(opts['before_match'])
		req.extend(pack('>L', len(opts_before_match)))
		req.extend(opts_before_match)

		opts_after_match = str_bytes(opts['after_match'])
		req.extend(pack('>L', len(opts_after_match)))
		req.extend(opts_after_match)

		opts_chunk_separator = str_bytes(opts['chunk_separator'])
		req.extend(pack('>L', len(opts_chunk_separator)))
		req.extend(opts_chunk_separator)

		req.extend(pack('>L', int(opts['limit'])))
		req.extend(pack('>L', int(opts['around'])))
		
		req.extend(pack('>L', int(opts['limit_passages'])))
		req.extend(pack('>L', int(opts['limit_words'])))
		req.extend(pack('>L', int(opts['start_passage_id'])))
		opts_html_strip_mode = str_bytes(opts['html_strip_mode'])
		req.extend(pack('>L', len(opts_html_strip_mode)))
		req.extend(opts_html_strip_mode)
		opts_passage_boundary = str_bytes(opts['passage_boundary'])
		req.extend(pack('>L', len(opts_passage_boundary)))
		req.extend(opts_passage_boundary)

		# documents
		req.extend(pack('>L', len(docs)))
		for doc in docs:
			doc = str_bytes(doc)
			req.extend(pack('>L', len(doc)))
			req.extend(doc)

		# send query, get response
		length = len(req)

		# add header
		req_head = bytearray()
		req_head.extend(pack('>2HL', SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, length))
		req_all = req_head + req
		self._Send ( sock, req_all )

		response = self._GetResponse(sock, VER_COMMAND_EXCERPT )
		if not response:
			return []

		# parse response
		pos = 0
		res = []
		rlen = len(response)

		for i in range(len(docs)):
			length = unpack('>L', response[pos:pos+4])[0]
			pos += 4

			if pos+length > rlen:
				self._error = 'incomplete reply'
				return []

			res.append(bytes_str(response[pos:pos+length]))
			pos += length

		return res

		Connect to searchd server and generate exceprts from given documents.
		
plugins/sphinx/class/sphinxapi.py