A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

PRDS - Programa de Residência em Desenvolvimento de Software

Apresentações semelhantes


Apresentação em tema: "PRDS - Programa de Residência em Desenvolvimento de Software"— Transcrição da apresentação:

1 PRDS - Programa de Residência em Desenvolvimento de Software
Laboratório de Engenharia de Software (LES) da PUC-Rio Carlos Lucena Rodrigo Paes Gustavo Carvalho Cidiane Lobato

2 Conteúdo Módulo 1: Java I – 4 horas
Sintaxe IDE Eclipse Módulo 2: Orientação a Objetos com Java I – 4 horas Herança Polimorfismo Associação Delegação Collections Módulo 3: Java II – 8 horas Manipulação de dados Persistência JDBC Sockets Módulo 4: UML – 8 horas Casos de Uso Classes Seqüência Módulo 5: Qualidade de Software I – 4 horas Teste Assertiva de execução Módulo 6: Orientação a objetos com Java II – 8 horas Padrões de projeto Frameworks © LES/PUC-Rio

3 Conteúdo Módulo 7: Java III – 12 horas
Mapeamento OO --> ER Persistência Hibernate Módulo 8: Desenvolvimento WEB I – 16 horas Servlets, JSP, Desenvolvimento de taglibs Arquitetura 3 camadas MVC básico Módulo 9: Desenvolvimento WEB II – 20 horas MVC Struts Internacionalização Módulo 10: Desenvolvimento WEB III – 28 horas MVC Spring Testes na camada WEB Appfuse © LES/PUC-Rio

4 Manipulação de Dados através de Fluxos Java

5 Fluxos de Java: Introdução
Muitos programas Java interagem com algum repositório de dados. Por ex., dados podem ser armazenados: em arquivos em uma unidade de disco rígido ou CD-ROM; nas páginas de um site da Web; na memória de um computador; em outro programa. Em Java, dados são recuperados e armazenados usando um sistema de comunicação denominado fluxos. É necessário criar fluxos de entrada para recuperar dados e fluxos de saída para armazená-los. © LES/PUC-Rio

6 Fluxos de Java: Introdução
Para obter dados, um programa abre um stream em uma fonte de dados (um arquivo, memória, um socket) e lê os dados seqüencialmente. Similarmente, um programa envia dados para um destino abrindo um stream associado ao destino e escrevendo nele seqüencialmente os dados. © LES/PUC-Rio

7 Fluxos de Java: Algoritmos
Independente da origem e dos tipos de dados, os algoritmos para recuperação (leitura) e armazenamento (escrita) dos dados são basicamente os mesmos: Reading open a stream while more information read information close the stream Writing open a stream while more information write information close the stream © LES/PUC-Rio

8 Fluxos de Java: Pacote e Hierarquias
O pacote “java.io” contém uma coleção de classes de fluxos que dão suporte aos algoritmos para leitura e escrita. Portanto, para utilizar fluxos de dados, um programa deve importar o pacote “java.io”. As classes de fluxos são organizadas em duas hierarquias de classes, baseadas nos tipos de dados (caracteres ou bytes). © LES/PUC-Rio

9 Fluxos de Byte: Visão Geral
Usados para leitura e escrita de bytes de 8 bits. Podem incluir dados numéricos, programas executáveis, comunicação na Internet e bytecodes. Tipicamente são usados para ler e escrever imagens e sons. Na verdade, qualquer tipo de dado imaginável pode ser (inclusive caracteres!) expresso usando uma série de bytes. Descendem das classes “InputStream” e “OutputStream”. “InputStream” fornece a API e a implementação parcial para fluxos de entrada (fluxos para leitura de bytes de 8 bits). “OutputStream” fornece a API e a implementação parcial para fluxos de saída (fluxos para escrita de bytes de 8 bits). Por ex., “ObjectInputStream” e “ObjectOutputStream” são classes usadas para serialização de objetos. © LES/PUC-Rio

10 Fluxos de Byte: “InputStream”
Para leitura de arquivos de bytes de 8 bits, usamos a classe “FileInputStream”. © LES/PUC-Rio

11 Fluxos de Byte: “OutputStream”
Para escrita de arquivos de bytes de 8 bits, usamos a classe “FileOutputStream”. © LES/PUC-Rio

12 Fluxos de Caractere: Visão Geral
Usados para leitura e escrita de caracteres de 16 bits. Podem tratar caracteres Unicode, ao passo que fluxos de byte limitam-se ao padrão ISO-Latin-1 (bytes com 8 bits). Para o tratamento de dados textuais, incluindo arquivos, páginas Web e outros tipos comuns de texto, recomenda-se sempre o uso de fluxos de caratere! Descendem das classes “Reader” e “Writer”. “Reader” fornece a API e a implementação parcial para fluxos de entrada (fluxos para leitura de caracteres de 16 bits). “Writer” fornece a API e a implementação parcial para fluxos de saída (fluxos para escrita de caracteres de 16 bits). © LES/PUC-Rio

13 Fluxos de Caracter: “Reader”
© LES/PUC-Rio

14 Fluxos de Caracter: “Writer”
© LES/PUC-Rio

15 Fluxos de Entrada: Reader e InputStream
“Reader” e “InputStream” definem APIs similares para caracteres e bytes, respectivamente. Por exemplo, “Reader” contém os seguintes métodos para leitura de caracteres e arrays de caracteres. int read() int read(char cbuf[]) int read(char cbuf[], int offset, int length) Da mesma forma, “InputStream” define os mesmos métodos para a leitura de bytes e arrays de bytes: int read(byte cbuf[]) int read(byte cbuf[], int offset, int length) © LES/PUC-Rio

16 Fluxos de Entrada: Reader e InputStream
No caso de um fluxo de entrada, o primeiro passo é criar um objeto que esteja associado à origem de dados. Por ex., se a origem for um arquivo em disco rígido, um objeto “FileInputStream”, poderá ser associado com este arquivo. Uma vez obtido o objeto de fluxo de entrada, é possível ler informações desse fluxo usando métodos do objeto. “FileInputStream” inclui um método “read()” que retorna um byte lido do arquivo. Ao acabar de usar os dados de um fluxo, um procedimento de finalização deve ser chamado. “FileInputStream” inclui um método “close()” para indicar que acabou de usar um arquivo. © LES/PUC-Rio

17 Fluxos de Saída: Writer e OutputStream
Similarmente… “Writer” e “OutputStream” definem APIs similares para caracteres e bytes, respectivamente. “Writer” contém os seguintes métodos para escrita de caracteres e arrays de caracteres. int write(int c) int write(char cbuf[]) int write(char cbuf[], int offset, int length) “OutputStream” define os mesmos métodos para a escrita de bytes e arrays de bytes: int write(byte cbuf[]) int write(byte cbuf[], int offset, int length) © LES/PUC-Rio

18 Fluxos de Entrada: Writer e OutputStream
No caso de um fluxo de saída, é criado primeiro um objeto associado ao destino dos dados. Tal objeto pode ser criado a partir da classe “BufferedWriter”, que representa um modo eficiente de criar arquivos de texto. Os dados são então escritos no objeto associado ao destino. O método “BufferedWriter.write()” envia caracteres individuais para o fluxo de saída. Assim como é feito com os fluxos de entrada, o fluxo é então finalizado. O método “BufferedWriter.close()” é chamado em um fluxo de saída quando não se têm mais informações a enviar. © LES/PUC-Rio

19 Fluxos de Arquivo: Exemplo “Copy”
import java.io.*; public class Copy { public static void main(String[] args) throws IOException { File inputFile = new File("farrago.txt"); File outputFile = new File("outagain.txt"); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } © LES/PUC-Rio

20 Fluxos de Arquivo: Exemplo “Copy”
O programa cria os objetos “File” que representam os arquivos “farrago.txt” e “outagain.txt” no sistema. O programa cria fluxos “FileReader” e “FileWriter” para os arquivos “farrago.txt” e “outagain.txt”. O programa lê o “reader” enquanto há caracteres no arquivo “farrago.txt” e escreve tais caracteres no “writer”. Quando a leitura da entrada termina, o programa fecha o “reader” e o “writer”. © LES/PUC-Rio

21 Fluxos de Arquivo: Exemplo “Copy”
Saída do programa: uma cópia exata de “farrago.txt” em um arquivo “outagain.txt” no mesmo diretório. Portanto, o conteúdo do arquivo “outagain.txt” é: So she went into the garden to cut a cabbage-leaf, to make an apple-pie; and at the same time a great she-bear, coming up the street, pops its head into the shop. 'What! no soap?' So he died, and she very imprudently married the barber; and there were present the Picninnies, and the Joblillies, and the Garyalies, and the grand Panjandrum himself, with the little round button at top, and they all fell to playing the game of catch as catch can, till the gun powder ran out at the heels of their boots. Samuel Foote © LES/PUC-Rio

22 Fluxos de Arquivo: Exemplo “CopyBytes”
import java.io.*; public class CopyBytes { public static void main(String[] args) throws IOException { File inputFile = new File("farrago.txt"); File outputFile = new File("outagain.txt"); FileInputStream in = new FileInputStream(inputFile); FileOutputStream out = new FileOutputStream(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } © LES/PUC-Rio

23 Fluxos de Arquivo: Exemplo “ReadBytes”
import java.io.*; public class ReadBytes { public static void main(String[] arguments) { try { FileInputStream file = new FileInputStream("class.dat"); boolean eof = false; int count = 0; while (!eof) { int input = file.read(); System.out.print(input + " "); if (input == -1) eof = true; else count++; } file.close(); System.out.println("\nBytes read: " + count); } catch (IOException e) { System.out.println("Error -- " + e.toString()); Fluxos de Arquivo: Exemplo “ReadBytes” © LES/PUC-Rio

24 Fluxos de Arquivo: Exemplo “ReadBytes”
Bytes read: 717 © LES/PUC-Rio

25 Fluxos de Arquivo: Exemplo “WriteBytes”
import java.io.*; public class WriteBytes { public static void main(String[] arguments) { int[] data = { 71, 73, 70, 56, 57, 97, 15, 0, 15, 0, 128, 0, 0, 255, 255, 255, 0, 0, 0, 44, 0, 0, 0, 0, 15, 0, 15, 0, 0, 2, 33, 132, 127, 161, 200, 185, 205, 84, 128, 241, 81, 35, 175, 155, 26, 228, 254, 105, 33, 102, 121, 165, 201, 145, 169, 154, 142, 172, 116, 162, 240, 90, 197, 5, 0, 59 }; try { FileOutputStream file = new FileOutputStream("pic.gif"); for (int i = 0; i < data.length; i++) file.write(data[i]); file.close(); } catch (IOException e) { System.out.println("Error -- " + e.toString()); } Fluxos de Arquivo: Exemplo “WriteBytes” © LES/PUC-Rio

26 Fluxos de Saída: Saída do Exemplo
© LES/PUC-Rio

27 Fluxos de Seqüência: Exemplo
O “SequenceInputStream” cria um único fluxo de entrada a partir de múltiplos fluxos de entrada. O programa “Concatenate” usa um SequenceInputStream a fim de concatenar arquivos seqüencialmente na ordem em que são especificados na linha de comando. © LES/PUC-Rio

28 Fluxos de Seqüência: Exemplo
© LES/PUC-Rio

29 Fluxos de Seqüência: Exemplo
“ListOfFiles” implementa a interface Enumeration. Após a criação do SequenceInputStream, o método main lê do fluxo um byte a cada vez. Para ler o InputStream de uma nova fonte, SequenceInputStream chama o “nextElement()” do objeto “Enumeration” a fim de obter o próximo InputStream. © LES/PUC-Rio

30 Fluxos Pipe: Introdução
Pipes: são usados para fazer um canal entre a saída de uma thread e a entrada de outra. “PipedReader” e “PipedWriter” (caracteres), bem como “PipedInputStream” e “PipedOutputStream” (bytes), implementam os componentes de entrada e saída de pipes. Por que pipes são úteis? © LES/PUC-Rio

31 Fluxos Pipe: Exemplo Considere uma classe que implementa vários métodos de manipulação de strings, tais como ordenação e reversão de caracteres em uma string. Seria interessante se a saída de um destes métodos pudesse ser usada como a entrada para outro de forma que uma série de chamadas de método pudesse ser usada como uma função de alto-nível. Por ex., se fosse necessário reverter cada palavra em uma lista, ordenar as palavras e então reverter novamente cada palavra a fim de criar uma lista de palavras “rhyming”... © LES/PUC-Rio

32 Fluxos Pipe: Exemplo Sem fluxos pipe, o programa teria que armazenar os resultados em algum lugar (em um arquivo ou na memória) entre cada passo. Com fluxos pipe, a saída de um método poderia ser “canalizada” para a entrada do próximo método. © LES/PUC-Rio

33 Fluxos Pipe: Exemplo © LES/PUC-Rio

34 Fluxos Pipe: Exemplo © LES/PUC-Rio

35 Fluxos Pipe: Exemplo © LES/PUC-Rio

36 Fluxos Pipe: Exemplo © LES/PUC-Rio

37 Fluxos Pipe: Exemplo O programa usa “PipedReader” e “PipedWriter” para conectar a entrada e saída dos métodos reverse e sort a fim de criar uma lista de palavras “rhyming”. A chamada mais interna ao método reverse recebe um “FileReader”, fluxo aberto no arquivo “words.txt”, que contém uma lista de palavras. O retorno de reverse é passado ao sort, que, por sua vez, tem seu retorno passado para a chamada mais externa ao método reverse. © LES/PUC-Rio

38 Fluxos Pipe: Exemplo No método reverse, as linhas de criação dos extremos de um pipe – um “PipedWriter” e um “PipedReader” – fazem também o PipedReader “ouvir" o PipedWriter. O método reverse inicia um “ReverseThread”, que escreve sua saída no PipedWriter, mas retorna o PipedReader (“ouvindo” o PipedWriter!) ao chamador. © LES/PUC-Rio

39 Fluxos Pipe: Exemplo O método reverse contém outros comandos interessantes: BufferedReader in = new BufferedReader(source); ... PrintWriter out = new PrintWriter(pipeOut); O programa lê de “BufferedReader”, que por sua vez lê de source, um fluxo “Reader”. O programa faz isso para se utilizar do conveniente método readLine de BufferedReader. Similarmente, a escrita do PipedWriter é lida por “PrintWriter” para que o programa possa usar o conveniente método println. A concatenção de fluxos é freqüente, pois permite a combinação de características dos vários tipos de fluxos. © LES/PUC-Rio

40 Exercícios Usando fluxos de byte (BufferedInputStream) e fluxos de dados primitivos (DataInputStream) para filtrar dados (FilterInputStream), implemente um programa “WritePrimes” que escreve os primeiros 400 números primos como inteiros em um arquivo chamado “400primes.dat”. Implemente também um programa “ReadPrimes” que lê os inteiros do arquivo “WritePrimes” e os apresenta. © LES/PUC-Rio

41 Persistência usando JDBC

42 Introdução JDBC (Java Database Connectivity): biblioteca de classes Java para conexão com bancos de dados (BDs) relacionais desenvolvidos por Microsoft, Sybase, Oracle, Informix, etc. Driver: ponte para um banco de dado relacional fornecido por uma empresa. Driver JDBC: ponte entre o JDBC e um banco de dado relacional fornecido por uma empresa. Gerenciador de Drivers: controla os drivers exigidos para o acesso aos registros de BDs, o que permite a independência de JDBC dos formatos BDs. © LES/PUC-Rio

43 Introdução Usando um driver JDBC como ponte para a fonte de dados, é possível recuperar e armazenar dados diretamente da linguagem Java. A biblioteca JDBC também um driver especial que a liga a outro padrão de conectividade de BDs chamado ODBC. ODBC: biblioteca da Microsoft para o acesso a BDs SQL; é gerenciado pelo ODBC Data Source Administrator. Ponte JDBC-ODBC: permite a conversão de chamadas JDBC para chamadas ODBC. © LES/PUC-Rio

44 Introdução Start -> Settings -> Control Panel -> ODBC Data Sources © LES/PUC-Rio

45 Visão Geral Usando JDBC (com ou sem ODBC), não há necessidade de adaptação a formatos específicos de BDs, porque: existem drivers que fazerm o acesso direto aos BDs; a linguagem SQL (padrão!) é utilizada no código. O JDBC inclui classes para cada uma das tarefas que costumam ser associadas à utilização de BDs: estabelecimento de uma conexão com um banco de dados; criação de uma consulta usando SQL; execução da consulta SQL no banco de dados; exibição dos registros resultantes. Portanto, classes que usam JDBC seguem o conhecido modelo de programação com instruções SQL. © LES/PUC-Rio

46 Visão Geral Na configuração de dados, porém, são possíveis duas alternativas: a ponte JDBC-ODBC ou um driver JDBC. Para usar a ponte JDBC-ODBC, é necessário: o driver JDBC-ODBC incluído com a linguagem Java 2: sun.jdbc.odbc.JdbcOdbcDriver; um driver ODBC; uma fonte de dados ODBC associada ao driver anterior usando o software ODBC Data Source Administrator. Para usar um driver JDBC, é necessário: obter e instalar o driver (não está incluído em Java!); associar uma fonte de dados ao driver JDBC. © LES/PUC-Rio

47 Usando JDBC-OBDC: Fontes de Dados
Todas as fontes de dados ODBC devem receber um nome descritivo curto. Este nome é usado em Java para estabelecer uma conexão com o banco de dados a que a fonte se refere. © LES/PUC-Rio

48 Usando JDBC-OBDC: Fontes de Dados
© LES/PUC-Rio

49 Usando JDBC-OBDC: Fontes de Dados
© LES/PUC-Rio

50 Usando JDBC-OBDC: Fontes de Dados
© LES/PUC-Rio

51 Usando JDBC-OBDC: Fontes de Dados
© LES/PUC-Rio

52 Usando JDBC-OBDC: Fontes de Dados
© LES/PUC-Rio

53 Usando JDBC-OBDC: Exemplo
© LES/PUC-Rio

54 Usando JDBC-OBDC: Exemplo
Entrada do programa: “Poland” Saída do programa: © LES/PUC-Rio

55 Usando um Driver JDBC: Fontes de Dados
Alguns drivers JDBC estão disponíveis para avaliação. O JDataConnectServer da NetDirect está disponível para download de teste a partir do endereço O JDataConnectServer usa o ODBC Data Source Administrator para criar uma nova fonte de dados associada a um banco de dados. © LES/PUC-Rio

56 Usando um Driver JDBC: Exemplo
© LES/PUC-Rio

57 Usando um Driver JDBC: Exemplo
Antes que o programa seja executado com êxito, o JDataConnectServer precisa ser iniciado. A referência a “localhost:1150” significa que: “localhost” é o nome da máquina que atua como servidor (a máquina local, neste caso); “1150” é o número de porta padrão em que o servidor JDataConnect é executado. O JDataConnectServer pode ser usado em servidores remotos na Internet, de modo que “localhost” poderia ser substituído por um endereço na Internet. © LES/PUC-Rio

58 JDBC: Carregando Drivers
Se a ponte JDBC-ODBC é usada, a seguinte linha de código carrega o driver: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); No caso de um driver JDBC, a documentação indica o nome a ser usado. Se o nome do driver é “jdbc.DriverXYZ”, então a seguinte linha carrega o driver: Class.forName("jdbc.DriverXYZ"); Não é necessário criar uma instância do driver, porque a chamada “Class.forName” faz isso automaticamente. Após o carregamento, o driver está disponível para efetuar conexões com um BD. © LES/PUC-Rio

59 JDBC: Estabelecendo a conexão
A forma geral para o estabelecimento de uma conexão é: Connection con = DriverManager.getConnection(url, "myLogin", "myPassword"); Se a ponte JDBC-ODBC é usada, a url começa por “jdbc:odbc:”. O resto da url é o nome da fonte de dados. Se uma fonte ODBC chamada “Fred” é usada, a url deve ser “jdbc:odbc:Fred”. Em "myLogin”, é colocado o nome usado para logar no BD; em “myPassword”, é colocada a senha. Se o nome e a senha são “Fernanda” e “J8”, as linhas a seguir estabelecem uma conexão: String url = "jdbc:odbc:Fred"; Connection con = DriverManager.getConnection(url, "Fernanda", "J8"); © LES/PUC-Rio

60 JDBC: Estabelecendo a conexão
Se um driver JDBC é usado, a documentação indica qual subprotocolo usar, isto é, o que colocar após “jdbc:” na url. Se “acme” é o subprotocolo, a url será “jdbc:acme:”. A documentação fornece outras diretivas se necessário. A última parte da “url” identifica a fonte de dados. O retorno do método “DriverManager.getConnection” é uma conexão aberta para a criação de comandos JDBC, os quais contêm instruções SQL a serem efetuadas sobre um BD. © LES/PUC-Rio

61 JDBC: Criando comandos
Um objeto Statement pode enviar um comando SQL ao gerenciador de BD. Para criar um objeto Statement, é necessária uma instância de uma conexão ativa. Na linha a seguir, um objeto Connection chamado “con” é usado para criar um comando Statement “stmt”: Statement stmt = con.createStatement(); Após a criação de um objeto Statement, deve ser executado sobre ele o comando SQL apropriado. Para um comando SELECT, o método de Statement usado é “executeQuery”. Para comandos que criam ou modificam tabelas, o método a usar é “executeUpdate”. Por exemplo: createTableCoffees = "CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)”; stmt.executeUpdate(createTableCoffees); © LES/PUC-Rio

62 JDBC: Recuperando valores
JDBC retorna o resultado de um comando em um objeto ResultSet. A linha a seguir declara o objeto ResultSet “rs” e assinala o resultado do comando “stmt” a “rs”: ResultSet rs = stmt.executeQuery( "SELECT COF_NAME, PRICE FROM COFFEES"); O objeto ResultSet “rs” contém linhas de cafés e preços. O método “next” move o cursor no objeto para a próxima linha. Sucessivas invocações de “next” movem o cursor uma linha por vez do início ao fim de “rs”. © LES/PUC-Rio

63 JDBC: Recuperando valores
O método getXXX recupera o valor de cada coluna. Por exemplo, a primeira coluna em cada linha de “rs” é “COF_NAME”, que armazena um valor de tipo SQL VARCHAR . O método para recuperação de um VARCHAR é getString. A segunda coluna armazena um valor de tipo SQL FLOAT. O método para recuperação de valores FLOAT é getFloat. A seguinte linha de código acessa os valores armazenados na linha corrente de “rs” e imprime cada linha com o nome seguido por três espaços e o preço. String query = "SELECT COF_NAME, PRICE FROM COFFEES"; ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String s = rs.getString("COF_NAME"); float n = rs.getFloat("PRICE"); System.out.println(s + " " + n); } © LES/PUC-Rio

64 JDBC: Resumo © LES/PUC-Rio

65 Exercícios Implemente um programa que usa a biblioteca JDBC para:
estabelecer uma conexão com uma fonte de dados; criar tabelas em um banco de dados associado à fonte; inserir dados nos campos das tabelas criadas; executar consultas no banco de dados usando SQL; exibir os registros recuperados através de consulta. Para fazer o exercício, use o tutorial da Sun sobre JDBC. © LES/PUC-Rio

66 Sockets

67 Protocolos de Redes Computadores na Internet se comunicam uns com os outros usando ou o “Transmission Control Protocol” (TCP) ou o “User Datagram Protocol” (UDP). © LES/PUC-Rio

68 Protocolos em Java: TCP e UDP
A programação Java se dá na camada de aplicação. Tipicamente, não é necessário conhecer detalhes internos da camada de transporte, que usa TCP e UDP. Em vez disso, o programador Java se utiliza das classes disponíveis no pacote “java.net”, que provêem comunicação em rede encapsulando detalhes dos protocolos. Contudo, para saber quais classes Java usar, é necessário entender as diferenças entre TCP e UDP. © LES/PUC-Rio

69 Características do TCP
Aplicações que precisam se comunicar com confiabilidade: estabelecem uma conexão e enviam os dados uma à outra através da conexão. Isto é análogo ao serviço de chamadas telefônicas. Como uma companhia telefônica, o TCP garante que: os dados enviados a partir de um extremo efetivamente chegam no outro extremo da conexão e, além disso, na mesma ordem em que foram enviados. Portanto, fornece um canal ponto a ponto para aplicações que requerem comunicação confiável. © LES/PUC-Rio

70 Aplicações TCP O “Hypertext Transfer Protocol” (HTTP) e o “File Transfer Protocol” (FTP) são aplicações que requerem confiabilidade. A ordem em que os dados são enviados e recebidos é crítica para o sucesso dessas aplicações. Por exemplo, quando o HTTP é usado para ler de uma URL, os dados devem ser recebidos na ordem em que são enviados. De outra forma, o resultado é um HTML mal formatado, um arquivo zip corrompido ou outras informações inválidas. Portanto, TCP é um protocolo baseado em conexão que provê um fluxo de dados confiável entre dois computadores. © LES/PUC-Rio

71 Características do UDP
Permite comunicação sem confiabilidade entre aplicações. UDP não é baseado em conexão como o TCP. Ao contrário, envia pacotes de dados independentes, chamados “datagramas”, de uma aplicação à outra. Isto é análogo ao serviço de correio: a ordem de entrega não é importante, pois cada mensagem é independente das outras. Também não há garantia de entrega. © LES/PUC-Rio

72 Aplicações UDP Um “servidor de relógio” é uma aplicação que envia a hora atual para os clientes que requisitam tal informação. Se o cliente perde um pacote, não faz sentido reenviá-lo. A confiabilidade do TCP é desnecessária, porque pode diminuir a performance e a utilidade do serviço. Outro exemplo é o comando “ping”, que testa a comunicação entre dois programas na rede. Ping não se importa de enviar/receber pacotes quebrados ou fora de ordem para determinar se a conexão é ou não boa. Um canal confiável invalidaria este serviço. Portanto, UDP é um protocolo que envia pacotes de dados independentes entre aplicações sem confiabilidade. © LES/PUC-Rio

73 Conceito de Portas Um computador possui uma única conexão “física” em uma rede. Todos os dados destinados para um computador chegam através desta conexão. Contudo, os dados podem ter sido enviados para aplicações diferentes. Tais dados são associados a uma aplicação específica através do uso de “portas”. Portanto, os dados têm seus destinos identificados através do par de identificadores relativos ao computador e à porta. O endereço do computador é o seu IP, com 32 bits. Uma porta é identificada por um número de 16 bits, usado por TCP e UDP para entregar dados à aplicação correta. © LES/PUC-Rio

74 Portas no TCP Usando TCP, uma aplicação servidor cria um “socket” para um número de porta específico. “Criar o socket” significa registrar a aplicação servidor no sistema para receber dados destinados a uma porta através de uma comunicação baseada em conexão. © LES/PUC-Rio

75 Portas no UDP Usando UDP, o pacote de datagramas contém o número da porta a que os dados são destinados; o UDP efetua então o roteamento para entregar o pacote à aplicação correta. © LES/PUC-Rio

76 Número de Portas Números de portas variam de uma faixa de 0 a porque as portas são representadas por números de 16 bits. Os números de portas variando de 0 a 1023 são restritas; elas são reservadas para uso de serviços conhecidos como HTTP e FTP e outros serviços de sistema. As aplicações não devem utilizar os números de portas restritas aos serviços bem conhecidos. © LES/PUC-Rio

77 Descrição de Sockets Um servidor roda em um computador específico e possui um socket associado a um número de porta específico: no lado do servidor, o servidor apenas espera, “ouvindo” no socket possíveis requisições de clientes; no lado do cliente, o cliente sabe o nome da máquina do servidor e o número da porta na qual o servidor está conectado. O cliente tenta estabelecer uma conexão através de uma requisição. © LES/PUC-Rio

78 Descrição de Sockets Se tudo está OK, o servidor aceita a conexão.
O servidor obtém um novo socket associado à mesma porta. Ele usa o novo socket de tal maneira que possa continuar a “ouvir” no socket original as requisições de clientes enquanto atende às necessidades do cliente conectado no novo socket. Se a conexão é aceita, um socket é criado do lado do cliente e pode ser usado para a comunicação com o servidor. © LES/PUC-Rio

79 Descrição de Sockets Formalizando: “socket” é um ponto extremo de uma comunicação bilateral entre dois programas sendo executados em uma rede. Exemplo: implementação de “EchoClient”, que se conecta ao servidor “Echo”. Este serviço está disponível em uma rede através da porta 7 e possui a função de receber dados de um cliente e “enviá-los” de volta. © LES/PUC-Rio

80 Exemplo de Cliente usando Socket
© LES/PUC-Rio

81 Exemplo de Cliente usando Socket
© LES/PUC-Rio

82 Exemplo de Cliente usando Socket
EchoClient é um programa “trivial” porque o servidor Echo implementa um protocolo simples. Programas que ouvem servidores HTTP são bem mais complexos. Contudo, o “esqueleto” básico de um cliente é: abrir um socket; abrir fluxos de entrada e saída no socket; ler e escrever nos fluxos de acordo com protocolo do servidor; fechar os fluxos; fechar o socket. Somente o passo 3 difere de cliente para cliente, dependendo do servidor. © LES/PUC-Rio

83 Servidor e Cliente usando Sockets
© LES/PUC-Rio

84 Servidor e Cliente usando Sockets
© LES/PUC-Rio

85 Servidor e Cliente usando Sockets
© LES/PUC-Rio

86 Servidor e Cliente usando Sockets
© LES/PUC-Rio

87 Servidor e Cliente usando Sockets
© LES/PUC-Rio

88 Servidor e Cliente usando Sockets
© LES/PUC-Rio

89 Exercícios Para manter a simplicidade do exemplo “KnockKnockServer”, o servidor foi projetado para ouvir e tratar apenas uma única requisição de conexão. Contudo, o servidor deve ser capaz de tratar múltiplas requisições simultaneamente. Neste caso, deve ser mantida uma fila de requisições, de tal maneira que o servidor possa tratá-las seqüencialmente. Reimplemente o servidor “KnockKnockServer” para a escuta e tratamento de múltiplas requisições simultaneamente (tutorial da Sun: use threads!). © LES/PUC-Rio

90 Referências [1] Tutorial da Sun Microsystems.
[2] Cadenhead, Rogers; Lemay, Laura. Java 2: professional reference. Rio de Janeiro, Campus, 2001. © LES/PUC-Rio


Carregar ppt "PRDS - Programa de Residência em Desenvolvimento de Software"

Apresentações semelhantes


Anúncios Google