1/6 Modelo Cliente-Servidor overhead do modelo OSI (TCP/IP), usar protocolo mais simples solicitação/resposta vantagens: simplicidade não é orientado a conecção pilha de protocolos menor que do OSI Cliente Kernel Servidor Kernel 7 6 Requisição / Resposta 5 4 3 Enlace 2 Físico 1 Exemplo Cliente-Servidor /*Definições necessárias aos clientes e aos servidores # define MAX_PATH 255 /* tamanho máximo do nome de um arquivo */ # define BUF_SIZE 1024 /*quantidade de dados a ser transferidos de uma vez*/ # define FILE_SERVER 243 /* endereço na rede do servidor de arquivos */ /* Definição das operações permitidas. */ # define CREATE 1 /* criar um novo arquivo */ # define READ 2 /* ler parte de um arquivo e retornar o que foi lido */ # define WRITE 3 /* escrever parte de um arquivo */ # define DELETE 4 /* apagar um arquivo existente /* /* Códigos de erro # define OK 0 /* operação realizada corretamente */ # define E_BAD_OPCODE 1 /* operação requisitada é desconhecida */ # define E_BAD_PARAM 2 /* erro em um parâmetro */ # define E_IO 3 /* erro no disco ou algum outro erro de entrada/saída */ /* Definição do formato a mensagem */ struct message{ long source; /* identificação do transmissor */ long dest; /* identificação do receptor */ long opcode; /* identificação da operação; CREATE, READ, etc. */ long count; /* quantidade de bytes transferir */ long offset; /* onde começar a ler ou escrever no arquivo */ long extra1; /* campo extra */ long extra2; /* campo extra */ long result; /* o resultado de uma operação é reportado aqui */ char nome[max_path]; /* nome do arquivo que estiver sendo operado */ char data[buf_size]; /* dados a serem lidos ou escritos */ }; Fig, 10.5 O arquivo header.h é usado tanto pelo cliente quanto pelo servidor.
2/6 # include <header.h> void main(void) { struct message mi, m2; /* Mensagens entrantes e saintes *,/ int r; /* código de resultado *,/ while(1){ /* servidor roda eternamente */ receive(file_server,&m1); / *bloqueado, esperando por uma mensagem */ switch (ml.opcode) { /* escalonamento baseado no tipo da requisição*/ case CREATE: r = do_create (&m1, &mm2); break; case READ: r = do_read (&m1, &m2); break; case WRITE: r = do_write (&m1, &m2); break; case DELETE: r = do_delete (&ml, &m2); break; default: r = E_BAD_OPCODE; } m2.result = r; /* retorna resultado para o cliente *,/ send (m1, source, &m2); /* envia resposta */ } } (a) # include <header.h> int copy (char *src, char *dst) { /* Procedimento para cópia de arquivo usando o servidor */ struct message m1; /* buffer de mensagem */ long position; /* current file position */ long client = 110 /* endereço do cliente */ initialize (); /* preparação para execução */ position = 0; do ( /* Obtém um bloco de dados do arquivo fonte. */ m1.opcode = READ; /* a operação é de leitura */ m1.offset = position; /* a posição corrente do arquivo */ m1.count = BUF_SIZE; /* quantidade de bytes a serem lidos */ strcpy(&m1.name, scr); /* cópia para a mensagem do nome do arquivo a ser lido */ send(file_server, &m1); /* envio da mensagem ao servidor de arquivos */ receive(client, &m1); /* bloqueado, aguardando resposta */ /* Escrita dos dados recebidos no arquivo destino. *./ m1.opcode = WRITE;. /* a operação é de escrita */ m1.offset = position; /* posição corrente do arquivo */ m1 count = m1.result; /* quantidade de bytes a serem escritos */ strcpy(&ml.name, dst); /* cópia do buffer do nome do arquivo a ser escrito*/ send(file_server, &ml); /* envio da mensagem ao servidor de arquivo */ receive(client, &m1); /* bloqueado, aguardando resposta */ position += ml.result; /* m1.result é o número de bytes escritos */ }while (ml.result > 0); /* iteração até a conclusão */ return (ml.result >=0? OK : m1.result); (b) "/ retorne OK ou um código de erros */ Fig, 10.6 (a) Um exemplo de servidor. (b) Um procedimento cliente, usando o servidor para copiar um arquivo.
3/6 Endereçamento Fig. 10.7 (a) Endereçamento máquina- processo (b) Endereçamento de processo em broadcast. (c) Uma procura de processo via servidor de nomes. Primitivas de Comunicação Bloqueadas X Não-Bloquadas Com Bufferização X Sem Bufferização Confiáveis X Não-Confiáveis Resumo Endereçamento Número da Máquina Endereços Esparços Nome ASCII buscados via servidor Bloqueio Primitivas bloqueadas Não-bloqueio com cópia para kernel Bufferização Não-bufferizado descartando mensagens que não são esperadas Não-bufferizado com armazenamento temporário das mensagens que não são esperadas Confiabilidade Não-confiável Requisição Confirmação Resposta Confirmação Não-bloqueio com interrupção Caixas postais Requisição Resposta Confirmação
4/6 Chamada Remota a Procedimento (RPC) o que é? Operações básicas *apresentação do C Chamadas por valor Chamdas por referência Fig.10.15 Chamadas e mensagens na chamada remota a procedimento. Cada uma das elipses representa um único processo, sendo que a parte sombreada representa o stub. 1. O procedimento do cliente chama o stub do cliente de maneira usual 2. O stub do cliente constrói uma mensagem e envia um trap ao kernel 3. O kernel envia uma mensagem ao kernel remoto 4. O kernel remoto entrega a mensagem ao stub do servidor 5. O stub do servidor descompacta os parâmetros constantes na mensagem e chama o servidor 6. O servidor realiza o seu trabalho e retorna o resultado para um buffer dentro do stub 7. O stub do servidor empacota tais resultados em uma mensagem e emite umtrap para o kernel 8. O kernel remoto envia a mensagem para o kernel do cliente 9. O kernel do cliente entrega a mensagem ao stub do cliente 10.O stub desempacota os resultados e os fornece ao cliente
5/6 Ligação Dinâmica Como o cliente encontra o servidor? Ao iniciar a execução do servidor, a chamada inicialize exporta a interface do servidor (ver código de programa) Esta informação é guardada pelo ligador (binder). Este processo é chamado de registro do servidor. Nome, nº versão, ID, manipulador cliente na primeira vez solicita impotação da interface. Semântica da Chamada Remota a Procedimento em Presença de Falhas 1. Cliente não é capaz de localizar o servidor. 2. A mensagem enviada do cliente para o servidor solicitando serviço foi perdida na rede. 3. A mensagem enviada do servidor para o cliente em resposta à solicitação foi perdida na rede. 4. O servidor sai do ar após ter recebido uma solicitação de serviço. 5. O cliente sai do ar após ter enviado uma solicitação de serviço. Aspectos Relativos à Implementação O sucesso ou fracasso do sistema distribuído depende fundamentalmente de sua performance. performance velocidade de comunicação aspectos de implementação Protocolos para Chamada Remota a Procedimentos Escolha do protocolo Protocolos orientados a conexão ou não orientados a conecção: vantagem ele controla os pacotes > redes WAN desvantagem perda de performance orientados a sem conecçaõ: maioria dos SDs em LAN Protocolos Padrão de propósito geral ou expecífico IP e UDP vantagem de uso de pacotes grandes
6/6 Confirmação *divisão de pacotes Pare-e-espere Rajadas Toda a mensagem Repetição seletiva comparar em LAN WAN Fluxo de controle (chips) Excesso de pacotes Introdução de retardo Caminho Crítico A sequência de instruções que é executada a cada chamada remota é denominada de caminho crítico. Em que parte do caminho crítico é consumido mais tempo? Copia A questão das cópias é um aspecto que domina os tempos gastos na execução das chamadas remotas. solução: scater-gather truque com memória virtual Gerência de Tempo O tempo de máquina gasto na gerência dos temporizadores não deve ser substimados Área de Problemas Transparência (Cliente/Servidor) Liguagens fracamente calcadas em tipo (C) grep rat < f5 sort > f6 O grep deve agir como cliente, escrevendo no servidor sort OU o sort deve funcionar como cliente lendo do servidor grep? Solução: pipeline dirigido a leitura pipeline dirigido a escrita*