quinta-feira, 26 de maio de 2011

Conceitos Básicos

Toda a comunicação entre processos em um sistema distribuído é baseada em trocas de mensagens, pois, conceitualmente, não há memória compartilhada., Quando vários processos precisam se comunicar, é necessária a adoção de protocolos ou seja, acordos entre as partes que se comunicam, sobre como a comunicação se dará (formatos, conteúdos e significados de mensagens). Cada sistema final na rede executa protocolos que controlam o envio e recepção de informações na rede.

Atualmente, o conjunto de protocolos da Internet – denominado TCP/IP [RFC 1180] – se tornou um padrão de facto em ambientes de sistemas distribuídos. Seus dois protocolos mais importantes são o TCP (Transmition Control Protocol) – orientado a conexões –, e o IP (Internet Protocol), motivo pelo qual esse conjunto de protocolo é conhecido como TCP/IP. A Figura 2.1 mostra a pilha de protocolos TCP/IP, comparando-a com as sete camadas do modelo ISO OSI.


As aplicações usualmente têm acesso aos protocolos de transporte da rede usando sockets. Um socket pode ser concebido como um portão de entrada e de saída de cada processo. Cada processo envia e/ou recebe mensagens através de seus sockets. Devido ao fato que, usualmente, os protocolos de transporte da rede são implementados e controlados pelo sistema operacional, um socket também pode ser concebido como uma interface entre a aplicação e o substrato de comunicação do sistema operacional.


A programação de sistemas distribuídos pode ser feita diretamente em uma linguagem de programação (ex. C, C++ ou Java), usando uma API (Application Program Interface – Interface de Programação de Aplicações) socket.

Interface de Programa Aplicativo

Dissemos que aplicativos cliente e servidor usam protocolos de transporte para se comunicar. Quando um aplicativo interage com o software de protocolo, ele deve especificar detalhes, por exemplo, se ele é um servidor ou um cliente (isto é, se esperará passivamente ou iniciará ativa­mente a comunicação). Além disso, aplicativos que se comunicam devem especificar detalhes adi­cionais (por exemplo, o remetente deve especificar os dados a serem enviados, o receptor deve especificar onde os dados recebidos devem ser colocados).
A interface que um aplicativo usa quando interage com o software de protocolo de transporte é conhecida como Interface de programa aplicativo, (Application program Inteiface, API). Como uma API define um conjunto de operações que um aplicativo pode executar quando ele interage com o software de protocolo, ela determina a funcionalidade á que está disponível. Além disso, detalhes, como os argumentos necessários determinam a dificuldade de criar um programa para usar a funcionalidade.
A maioria dos sistemas de programação define uma APl listando um conjunto de procedimentos disponíveis para os aplicativos, os argumentos que cada procedimento espera e os tipos de dados. Normalmente, uma API contém um procedimento separado para cada função lógica. Por exemplo, ela poderia conter um procedimento usado para estabelecer uma comunicação e outro procedimen­to usado para enviar dados.

A API de Socktes

Os padrões de protocolos de comunicação usualmente não especificam a API que os aplicativos de­vem usar para interagir com os protocolos. Em vez disso, os protocolos especificam as operações gerais que devem ser fornecidas e permitem que cada sistema operacional defina a API específica que um aplicativo deve usar para executar as operações. Deste modo, um padrão de protocolo po­deria sugerir que uma operação é necessária para permitir que um aplicativo envie dados, e a API especifica o nome exato da função e o tipo de cada argumento.
Embora padrões de protocolo permitam aos projetistas de sistema operacional escolher uma API, muitos adotaram a API de sockets. A API de sockets está disponível para muitos sistemas opera­cionais, incluindo os usados em computadores pessoais (por exemplo, os sistemas Windows da Mi­crosoft) e vários sistemas UNIX (por exemplo, o Solaris, da Sun Microsystems).
A API de sockets se originou como parte do sistema operacional de BSD UNIX. O trabalho foi fi­nanciado por uma bolsa do governo, através da qual a University of California, em Berkeley, desenvolveu e distribuiu uma versão de UNIX que continha protocolos de ligação inter-redes TCP/IP. Muitos vendedores de computadores portaram o sistema BSD para seu hardware o usaram co­mo base em seus sistemas operacionais comerciais. Deste modo, a API de sockets se tornou o pa­drão de facto na indústria.
Para resumir: A interface entre um programa aplicativo e os protocolos de comunicação em um sistema operacional é conhecida como interface de programa de Aplicativos, ou API. A API de sockets é um padrão de facto.

Socktes em Java

O socket é uma abstração que representa um ponto de comunicação em uma rede de computadores [Harold 1997]. Para dois computadores trocarem informações, cada um utiliza um socket. Tipicamente, um computador atua como servidor, abrindo o socket e ficando na escuta, a espera de mensagens ou pedidos de conexões. O outro computador assume o papel de cliente, enviando mensagens para o socket do servidor.
Existem dois modos de operação: orientado a conexão, baseado no protocolo TCP (Transport Control Protocol) e sem conexão, empregando o protocolo UDP (User Datagram Protocol). Para usar sockets orientados a conexão, antes do envio dos dados é necessário o estabelecimento de uma conexão entre o cliente e o servidor. A conexão deve ser terminada ao final da comunicação e os dados chegam na mesma ordem que foram enviados. Quando sockets sem conexão são empregados, a entrega não é garantida. Dados podem chegar em ordem diferente da que foram enviados. O modo usado depende das necessidades da aplicação. Via de regra, o uso de conexão implica em maior confiabilidade, porém com maior overhead.
Cada computador em uma rede TCP/IP possui endereço IP único. Portas representam conexões individuais com esse endereço. Quando o socket é criado, ele deve ser associado com uma porta específica, isto é, efetuar o seu binding. Para estabelecer uma conexão o cliente precisa conhecer o endereço IP da máquina onde o servidor executa e o número da porta que o servidor está escutando. Existe a tentativa de padronização de alguns números de portas com relação aos serviços oferecidos pelo servidor, tais como: 7-echo, 13-daytime, 21-ftp, 23-telnet, 25-smtp, 79-finger, 80-http, 110-pop3. Estes números de portas são definidos pela IANA (Internet Assigned Numbers Authority).
A figura a baixo, mostra o algoritmo básico para clientes e servidores quando TCP é usado. Em Java, clientes e servidores adotam procedimentos diferentes. Um socket cliente é criado e conectado pelo construtor da classe Socket. Por exemplo:

clientSocket = new Socket(“merlin.das.ufsc.br”, 80);

A comunicação em si é feita com o auxílio de classes tipo streams, que são classes do pacote java.io. Os clientes seguem sempre a mesma receita básica: cria um socket com conexão cliente e utiliza classes que implementam streams para efetuar a comunicação. Existem diversas opções para sockets clientes, tais como definir o timeout usado no protocolo de desconexão, timeout utilizado em operações de leitura, etc.


Servidores não criam conexões, eles esperam pelo pedido de conexão de um cliente. O construtor de ServerSocket é usado, como em:

ServerSocket serverSocket = new ServerSocket(80, 5);

Um servidor pode receber várias requisições de conexão ao mesmo tempo e as requisições são processadas uma a uma. A fila de requisições ainda não atendidas é denominada pilha de escuta. O tamanho da fila de escuta indica quantas requisições de conexão simultâneas são mantidas. Assim, na construção acima, o primeiro parâmetro é o número da porta a ser escutada e o segundo parâmetro é o tamanho da pilha de escuta. O valor default é 50. O método accept() é chamado para retirar requisições da fila. Ele bloqueia o processo até a chegada uma requisição, e após isso, retorna um socket conectado com o cliente. O objeto socket do servidor não é usado, um novo é criado para a transferência dos dados. O socket do servidor continua enfileirando pedidos de conexão. Finalmente, streams são usados para a troca de dados. Um servidor simples processa uma conexão de cada vez. Entretanto, utilizando múltiplas threads, um servidor concorrente vai criar uma nova thread para cada conexão aberta e assim consegue processar várias conexões simultaneamente. Por exemplo, servidores web comerciais são todos concorrentes.
No caso de comunicação baseada em datagramas, a classe DatagramSocket é usada tanto por clientes como por servidores. O servidor deve especificar sua porta, e a omissão do parâmetro significa “use a próxima porta livre”. O cliente sempre utiliza a próxima. O algoritmo básico é mostrado na figura a baixo:


A classe DatagramPacket é usada para enviar e receber dados. Ela contém informações para conexão e os próprios dados. Para receber dados de um socket datagrama, o método receive() bloqueia até a recepção dos dados. Para enviar dados para um socket datagrama é necessário um endereço, a classe InetAddress representa endereços na Internet. Por exemplo:

InetAddress addr = InetAddress.getByName(“das.ufsc.br”).

O envio de um string para um socket destinatário é feito através da montagem de um objeto DatagramPacket, o qual conterá a mensagem e o endereço destino. Seu envio através do método send() de objeto da classe DatagramSocket criado anteriormente pelo cliente.

link para Download do trabalho escrito.

http://www.megaupload.com/?d=M1URWC4J

Vídeo aula sobre Sockets