Tópicos em Bancos de Dados: Sistemas de Informação Inteligentes 1997/2


 

Implementação de clientes


A implementação de sistemas cliente / servidor usando RPC requer a definição e o registro de uma interface específica. Veja a  definição da interface deste servidor para mais detalhes. Cada interface registrada é acessada pelo cliente especificando o nome e a versão do servidor que se deseja utilizar, além do nome da máquina em que o servidor está sendo executado.

Neste trabalho, definimos um servidor de nome TREC_SERVER com apenas uma versão, de nome TBD97_2. O servidor está executando na máquina solimoes.dcc.ufmg.br.

Como utilizar o servidor

O servidor fica executando eternamente na máquina servidora aguardando solicitações de serviços por parte dos clientes. Quando o servidor recebe um pedido, o processo cliente fica bloqueado aguardando a resposta, ou uma mensagem de erro caso haja alguma falha com servidor. O servidor processa o pedido e envia a resposta de volta, quando o cliente volta ao processamento normal, já com os dados de resposta.

A seguir apresentamos os nomes, os parâmetros e os tipos de dados retornados pelos serviços implementados. Observe atentamente que todos os serviços retornam ponteiros e nunca estruturas nem dados.
 
 

lista_inv *lista_invertida_1( 
 texto *p, CLIENT *cl)
Retorna o identificador do termo correspondente à palavra passada como parâmetro, e a lista invertida deste termo.
lista_term_freq *termos_documento_1( 
 documento *d, CLIENT *cl)
Retorna uma lista de tuplas contendo todos os termos de um documento, passado como parâmetro, e suas respectivas frequências dentro daquele documento.
texto *fonte_documento_1( 
 documento *d, CLIENT *cl)
Retorna um string que é o texto em linguagem natural de um documento, passado como parâmetro.
lista_nor *norma_documentos_1( 
 lista_doc *ld, CLIENT *cl)
Rertorna uma lista contendo as normas dos documentos contidos numa lista de documentos, passada como parâmetro. A ordem da listas é a mesma.
lista_idf *idf_termos_1( 
 lista_ter *lt, CLIENT *cl)
Retorna uma lista contendo os idfs dos termos da lista de termos passada como parâmetro. A ordem das listas também é a mesma.
Note que todas as funções terminam com o sufixo (_1) corresponde ao número da versão implementada.

Código de acesso ao servidor

Vamos descrever o código básico para se utilizar um serviço remoto qualqer. O primeiro passo é criar uma referência para chamadas de procedimentos remotos: A variável servidor no código acima contém o nome da máquina em que o processo está executando. Repare que além do programa e de sua versão, especificamos que a comunicação com o servidor deve ser usando o protocolo TCP/IP. Isto é importante por questões de confiabilidade. No nosso caso é imprescindível o uso de TCP/IP por que o volume de dados trocado é muito grande.

Observe que o resultado da chamada é armazenado numa variável ponteiro (cl). Esta variável será utilizada posteriormente quando da chamada efetiva do procedimento remoto. No exemplo a seguir, fazemos uma chamada ao procedimento remoto que retorna o texto fonte de um documento. No nosso exemplo, do documento 365799:

Note que tanto o parâmetro passado ao procedimento quanto o valor retornado são referenciados através de ponteiros e não através de referências diretas. Isto é uma peculiaridade do protocolo RPC.

A variável resposta é local, portanto podemos utilizá-la normalmente sem nenhum procedimento especial. O trecho a seguir imprime o conteúdo da resposta (note que resposta é um ponteiro para um texto).


Finalizando o cliente

Após utilizar o servidor, o cliente deve liberar a memória alocada para cada resposta aos serviços e destruir o identificador de cliente criado. Ainda sobre o exemplo descrito acima, temos: Observe que fazemos a conversão (casting) do ponteiro resposta para o tipo char.
Naturalmente este código deve ser inserido no final do programa cliente.


Compilando o cliente

Nesta seção vamos discutir o processo de compilação de um cliente para o servidor TREC. Além do próprio código fonte do programa precisamos de três arquivos gerados por um compilador específico para aplicações que usam RPC. Estes arquivos são gerados apenas uma vez e compilados usando um compilador C normal, portanto os clientes não precisam se ater ao compilador de RPC.

Veja como pegar e utilizar estes e outros arquivos.

O arquivo de interface (trec.x) é compilado e gera quatro novos arquivos:

 
trec.h contém definições de tipos de uso geral para o cliente e para o servidor
trec_clnt.c  contém código e definições de comunicação para o lado cliente da aplicação
trec_svc.c  contém código e definições de comunicação para o lado servidor da aplicação
trec_xdr.c contém definições para conversão de dados entre os processos
Vale salientar que precisamos gerar o código binário a partir do arquivo trec_xdr.c antes de usá-lo. O comando a seguir faz isso: Este comando vai gerar um arquivo binário compilado de nome trec_xdr.o que será usado na compilação efetiva do cliente. Este comando só precisa ser executado uma vez.

Um programa cliente é um programa normal em C, com a mesma estrutura de um programa qualqer. As únicas diferenças são que o arquivo trec.h precisa ser incluído no programa e os comandos especiais de RPC que já foram citados acima. No momento da compilação precisamos incluir o "lado cliente da aplicação gerada pelo sistema", através do seguinte comando:

O resultado do comando acima será um arquivo executável de nome cliente. Evidentemente que outras opções de compilação podem e devem ser incluídas nesta linha de comando.