Redes de Computadores Programação com Sockets Prof. Othon Batista ([email protected]) Página 1 Roteiro • • • • • • Introdução A Arquitetura TCP/IP O Protocolo IP O Protocolo UDP O Protocolo TCP Qual Protocolo Usar: UDP ou TCP? • Socket com TCP • Socket com TCP: Exemplo de Aplicação • Socket com UDP • Socket com UDP: Exemplo de Aplicação • Servidor Web Simples Prof. Othon Batista ([email protected]) Página 2 Introdução Objetivo: aprender a construir aplicações cliente/servidor usando sockets. • Os sockets apareceram pela primeira vez em uma implementação do BSD Unix 4.1 em 1981. – Devem ser explicitamente criados, usados e liberados. – Paradigma cliente/servidor. – São a forma mais usada de comunicação entre processos (IPC – Inter Process Communication). • Há dois tipos de sockets: UDP e TCP. Prof. Othon Batista ([email protected]) Página 3 A Arquitetura TCP/IP Aplicações cliente/servidor Serviço orientado à conexão e confiável. SEGMENTO Aplicação TCP UDP IP Rede Física Serviço não orientado à conexão e não confiável. DATAGRAMA Serviço não orientado à conexão e não confiável. DATAGRAMA • Comunicação através de endereços IP e portas lógicas. Prof. Othon Batista ([email protected]) Página 4 A Arquitetura TCP/IP • Os endereços IP são formados por quatro números, tipicamente separados por pontos. • Cada número tem o tamanho de 1 byte (0 – 255). • Exemplo: 10.125.3.45 • Alguns endereços IP são reservados (não nos interessam neste momento)! • Há também os nomes simbólicos, que devem ser traduzidos para endereços IP por algum serviço, tal como o DNS. Exemplo: www.fib.br. Prof. Othon Batista ([email protected]) Página 5 Arquitetura TCP/IP • Convenção para os números de portas: – 0 até 1023 ⇒ portas privilegiadas; – 1024 até 65535 ⇒ portas sem restrições. • Algumas portas privilegiadas: – – – – – FTP ⇒ 20 e 21 Telnet ⇒ 23 SMTP ⇒ 25 POP3 ⇒ 110 DNS ⇒ 53 Não use estas portas. A não ser que você saiba o que está fazendo! Prof. Othon Batista ([email protected]) Página 6 O Protocolo IP • • • • • Camada mais baixa da arquitetura TCP/IP. Não é fim-a-fim. Não orientada à conexão. Usada pelos protocolos UDP e TCP. Serviço de datagrama não confiável: – a entrega de um datagrama não é garantida; – os datagramas podem ser entregues fora de ordem; – podem ser recebidos datagramas duplicados. • A confiabilidade é dada nas camadas acima! Prof. Othon Batista ([email protected]) Página 7 O Protocolo UDP datagramas UDP • • • • • • Usado diretamente pelos programas. É fim-a-fim. Não orientado à conexão. Serviço de datagrama não confiável. Mais ágil de TCP. Usado por: DNS, NFS, SNMP, RIP... Prof. Othon Batista ([email protected]) Página 8 O Protocolo TCP segmentos TCP • • • • • Usado diretamente pelos programas. É fim-a-fim. Orientado à conexão. Serviço confiável. Usado por: FTP, TELNET, SMTP, POP3... Prof. Othon Batista ([email protected]) Página 9 Qual Protocolo Usar : UDP ou TCP? • TCP deve ser escolhido para aplicações que necessitam de transferência de dados confiável, por exemplo: – transferência de arquivos (FTP); – terminais virtuais (TELNET). • UDP deve ser escolhida para: – aplicações simples de pedido/resposta (DNS); – aplicações que podem tolerar transmissões de dados não confiáveis (protocolos de roteamento, tal como RIP). Prof. Othon Batista ([email protected]) Página 10 Socket com TCP Um socket é uma porta entre o processo de aplicação e um protocolo de transporte fim-a-fim. controlado pelo programador de aplicação controlado pelo sistema operacional processo processo socket TCP com buffers, variáveis Cliente Internet socket TCP com buffers, variáveis controlado pelo programador de aplicação controlado pelo sistema operacional Servidor Prof. Othon Batista ([email protected]) Página 11 Socket com TCP • O processo servidor deve estar em execução. • O servidor deve ter criado socket que aguarda contato do cliente. • O cliente cria socket TCP local. • O cliente especifica endereço IP, número de porta do processo servidor. • Quando o cliente cria um socket, o TCP do cliente estabelece conexão com TCP do servidor • Quando contatado pelo cliente, o TCP do servidor cria socket novo para que o processo servidor possa se comunicar com o cliente – o servidor conversa com múltiplos clientes Prof. Othon Batista ([email protected]) Página 12 Socket com TCP ponto de vista da aplicação TCP provê transferência confiável, ordenada de bytes (“tubo”) entre cliente e servidor Prof. Othon Batista ([email protected]) Página 13 Socket com TCP: Exemplo de Aplicação do_usuario do_servidor Fluxo de entrada: seqüência de bytes recebida pelo processo. Fluxo de saída: seqüência de bytes transmitida pelo processo. para_servidor • Cliente lê linha da entrada padrão (doUsuário), envia para servidor via socket (paraServidor). • Servidor lê linha do socket. • Servidor converte linha para letras maiúsculas, devolve para o cliente. • Cliente lê linha modificada do socket (doServidor), imprime-a. socket do cliente Prof. Othon Batista ([email protected]) Página 14 Servidor Socket com TCP: Exemplo de Aplicação (executa em nomeHosp) cria socket, porta=x, para receber pedido: socketRecepção = ServerSocket () TCP aguarda chegada de configuração pedido de conexão socketConexão = socketRecepção.accept() lê pedido de socketConexão escreve resposta para socketConexão fecha socketConexão Cliente cria socket, abre conexão a nomeHosp, porta=x socketCliente = Socket() Envia pedido usando socketCliente lê resposta de socketCliente fecha socketCliente Prof. Othon Batista ([email protected]) Página 15 Socket com TCP: Exemplo de Aplicação (Cliente) import java.io.*; import java.net.*; class ClienteTCP { public static void main(String argv[]) throws Exception { String frase; String fraseModificada; Cria fluxo de entrada Cria socket de cliente, conexão ao servidor Cria fluxo de saída ligado ao socket BufferedReader doUsuario = new BufferedReader(new InputStreamReader(System.in)); Socket socketCliente = new Socket(”nomeHosp", 6789); DataOutputStream paraServidor = new DataOutputStream(socketCliente.getOutputStream()); Prof. Othon Batista ([email protected]) Página 16 Socket com TCP: Exemplo de Aplicação (Cliente) Cria fluxo de entrada ligado ao socket BufferedReader doServidor = new BufferedReader(new InputStreamReader(socketCliente.getInputStream())); frase = doUsuario.readLine(); Envia linha ao servidor paraServidor.writeBytes(frase + '\n'); fraseModificada = doServidor.readLine(); Lê linha do servidor System.out.println(”Do Servidor: " + fraseModificada); socketCliente.close(); } } Prof. Othon Batista ([email protected]) Página 17 Socket com TCP: Exemplo de Aplicação (Servidor) import java.io.*; import java.net.*; class servidorTCP { Cria socket para recepção na porta 6789 Aguarda, no socket para recepção, o contato do cliente Cria fluxo de entrada, ligado ao socket public static void main(String argv[]) throws Exception { String fraseCliente; StringfFraseMaiusculas; ServerSocket socketRecepcao = new ServerSocket(6789); while(true) { Socket socketConexao = socketRecepcao.accept(); BufferedReader doCliente = new BufferedReader(new InputStreamReader(socketConexao.getInputStream())); Prof. Othon Batista ([email protected]) Página 18 Socket com TCP: Exemplo de Aplicação (Servidor) Cria fluxo de saída, ligado ao socket DataOutputStream paraCliente = new DataOutputStream(socketConexão.getOutputStream()); Lê linha do socket fraseCliente= doCliente.readLine(); fraseEmMaiusculas= fraseCliente.toUpperCase() + '\n'; Escreve linha ao socket paraClient.writeBytes(fraseEmMaiusculas); } } } Final do elo while, volta ao início e aguarda conexão de outro cliente Prof. Othon Batista ([email protected]) Página 19 Socket com UDP • • • • UDP não estabelece conexão. remetente coloca explicitamente endereço IP e porta do destino. servidor deve extrair endereço IP, porta do remetente do datagrama recebido. Os dados transmitidos podem ser recebidos fora de ponto de vista da aplicação ordem, ou perdidos. UDP provê transferência não confiável de grupos de bytes (“datagramas”) entre cliente e servidor Prof. Othon Batista ([email protected]) Página 20 Socket com UDP Servidor (executa em nomeHosp) cria socket, porta=x, para pedido que chega: socketServidor = DatagramSocket() lê pedido do socketServidor escreve resposta ao socketServidor especificando endereço IP, número de porta do cliente Cliente cria socket, socketCliente = DatagramSocket() cria, endereça (nomeHosp, porta=x, envia pedido em datagrama usando socketCliente lê resposa do socketCliente fecha socketCliente Prof. Othon Batista ([email protected]) Página 21 Socket com UDP: Exemplo de Aplicação (Cliente) Prof. Othon Batista ([email protected]) Página 22 Socket com UDP: Exemplo de Aplicação (Cliente) import java.io.*; import java.net.*; Cria fluxo de entrada Cria socket de cliente Traduz nome de hospedeiro ao endereço IP usando DNS class clienteUDP { public static void main(String args[]) throws Exception { BufferedReader do Usuario= new BufferedReader(new InputStreamReader(System.in)); DatagramSocket socketCliente = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName(”nomeHosp"); byte[] sendData = new byte[1024]; byte[] receiveData = new byte[1024]; String frase = doUsuario.readLine(); sendData = frase.getBytes(); Prof. Othon Batista ([email protected]) Página 23 Socket com UDP: Exemplo de Aplicação (Cliente) Cria datagrama com dados para enviar, comprimento, endereço IP, porta Envia datagrama ao servidor DatagramPacket pacoteEnviado = new DatagramPacket(dadosEnvio, dadosEnvio.length, IPAddress, 9876); socketCliente.send(pacoteEnviado); DatagramPacket pacoteRecebido = new DatagramPacket(dadosRecebidos, dadosRecebidos.length); Lê datagrama do servidor socketCliente.receive(pacoteRecebido); String fraseModificada = new String(pacoteRecebido.getData()); System.out.println(”Do Servidor:" + fraseModificada); socketCliente.close(); } } Prof. Othon Batista ([email protected]) Página 24 Socket com UDP: Exemplo de Aplicação (Servidor) Prof. Othon Batista ([email protected]) Página 25 Socket com UDP: Exemplo de Aplicação (Servidor) import java.io.*; import java.net.*; Cria socket para datagramas na porta 9876 class servidorUDP { public static void main(String args[]) throws Exception { DatagramSocket socketServidor = new DatagramSocket(9876); byte[] dadosRecebidos = new byte[1024]; byte[] dadosEnviados = new byte[1024]; Aloca memória para receber datagrama Recebe datagrama while(true) { DatagramPacket pacoteRecebido = new DatagramPacket(dadosRecebidos, dadosRecebidos.length); socketServidor.receive(pacoteRecebido); Prof. Othon Batista ([email protected]) Página 26 Socket com UDP: Exemplo de Aplicação (Servidor) String frase = new String(pacoteRecebido.getData()); Obtém endereço IP, no. de porta do remetente InetAddress IPAddress = pacoteRecebido.getAddress(); int porta = pacoteRecebido.getPort(); String fraseEmMaiusculas = frase.toUpperCase(); dadosEnviados = fraseEmMaiusculas.getBytes(); Cria datagrama p/ enviar ao cliente Escreve datagrama no socket } DatagramPacket pacoteEnviado = new DatagramPacket(dadosEnviados, dadosEnviados.length, IPAddress, porta); socketServidor.send(pacoteEnviado); } } ‘ Fim do elo while, volta ao início e aguarda chegar outro datagrama Prof. Othon Batista ([email protected]) Página 27 Servidor Web Simples • Funções do servidor Web: – Trata apenas um pedido HTTP por vez – Aceita e examina o pedido HTTP – Recupera o arquivo pedido do sistema de arquivos do servidor – Cria uma mensagem de resposta HTTP consistindo do arquivo solicitado precedido por linhas de cabeçalho – Envia a resposta diretamente ao cliente. Prof. Othon Batista ([email protected]) Página 28 Servidor Web Simples Contém a classe StringTokenizer que é usada para examinar o pedido Primeira linha da mensagem de pedido HTTP e Nome do arquivo solicitado Aguarda conexão do cliente import java.io.*; import java.net.*; import java.util.*; class WebServer { public static void main(String argv[]) throws Exception { String requestMessageLine; String fileName; ServerSocket listenSocket = new ServerSocket(6789); Socket connectionSocket = listenSocket.accept(); Cria fluxo de Entrada BufferedReader inFromClient = new BufferedReader(new InputStreamReader( connectionSocket.getInputStream())); Cria fluxo de Saída DataOutputStream outToClient = new DataOutputStream( connectionSocket.getOutputStream()); Prof. Othon Batista ([email protected]) Página 29 Servidor Web Simples Lê a primeira linha do pedido HTTP que deveria ter o seguinte formato: GET file_name HTTP/1.0 Examina a primeira linha da mensagem para extrair o nome do arquivo Associa o fluxo inFile ao arquivo fileName Determina o tamanho do arquivo e constrói um vetor de bytes do mesmo tamanho requestMessageLine = inFromClient.readLine(); StringTokenizer tokenizedLine = new StringTokenizer(requestMessageLine); if (tokenizedLine.nextToken().equals("GET")){ fileName = tokenizedLine.nextToken(); if (fileName.startsWith("/") == true ) fileName = fileName.substring(1); File file = new File(fileName); int numOfBytes = (int) file.length(); FileInputStream inFile = new FileInputStream ( fileName); byte[] fileInBytes = new byte[]; inFile.read(fileInBytes); Prof. Othon Batista ([email protected]) Página 30 Servidor Web Simples Inicia a construção da mensagem de resposta outToClient.writeBytes( "HTTP/1.0 200 Document Follows\r\n"); if (fileName.endsWith(".jpg")) outToClient.writeBytes("Content-Type: image/jpeg\r\n"); if (fileName.endsWith(".gif")) outToClient.writeBytes("Content-Type: image/gif\r\n"); outToClient.writeBytes("Content-Length: " + numOfBytes + "\r\n"); outToClient.writeBytes("\r\n"); Transmissão do cabeçalho da resposta HTTP. outToClient.write(fileInBytes, 0, numOfBytes); connectionSocket.close(); } else System.out.println("Bad Request Message"); } } Prof. Othon Batista ([email protected]) Página 31