Introdução aos Sockets Java Fábio Favarim [email protected] DAS – Departamento de Automação e Sistemas UFSC – Universidade Federal de Santa Catarina 26/09/2005 LCMI - DAS - UFSC 1 Sumário ● Introdução ● Sockets TCP ● Sockets UDP ● Sockets Multicast ● Referências 26/09/2005 LCMI - DAS - UFSC 2 Introdução ● ● Toda a comunicação entre processos em um sistema distribuído é, normalmente, baseada em trocas de mensagens. Quando vários processos precisam se comunicar, é necessária a adoção de protocolos, para que possam se entender. Protocolo Meio de Transmissão 26/09/2005 LCMI - DAS - UFSC 3 Com licença? Protocolos Solicita conexão Pois não... Aceita conexão Que horas são? Envia mensagem São 10h15. Confirma recepção Com licença? Fecha Conexão De nada. Libera Conexão Tempo 26/09/2005 LCMI - DAS - UFSC 4 O que são sockets? • São abstrações que representam pontos de comunicação através dos quais processos se comunicam; • Para que dois computadores possam trocar informações – Cada um utiliza um socket. Aplicação Sistema Operacional 26/09/2005 Processo socket TCP ou UDP Rede LCMI - DAS - UFSC Processo socket TCP ou UDP 5 Cliente/Servidor ● Os sockets adotam o paradigma cliente/servidor. – Um computador é o Servidor: abre o socket e fica na escuta, a espera de mensagens ou pedidos de conexões dos clientes – O outro é o Cliente: envia mensagens para o socket servidor Requisita serviço Fornece serviço Que horas são? São 10:20 da manhã. SERVIDOR CLIENTE Os papeis de clientes e servidores não são fixos em processos: um servidor pode ser cliente de outro serviço. 26/09/2005 LCMI - DAS - UFSC 6 Sockets na Internet ● ● ● Na Internet, cada máquina têm um endereço único: Endereço IP Cada endereço IP possui portas associadas, que representam conexões individuais com este endereço Algumas portas conhecidas: echo(7) ftp(21) telnet(23) http(80) pop3(110) ● Definidas pela IANA (Internet Assigned Numbers Authority) ● Para se comunicar com um servidor, um cliente precisa: – – Endereço IP da máquina onde o servidor executa Número da porta que o servidor escuta. Ex: 221.13.45.6:80. Binding: quando o socket é criado, uma porta deve ser associada 26/09/2005 LCMI - DAS - UFSC ● 7 Modos de Operação ● Orientado a conexão: TCP (Transport Control Protocol) – As mensagens são enviadas através de um canal de comunicação Canal de Comunicação ● Sem conexão: UDP (User Datagram Protocol) – 26/09/2005 As mensagens de tamanho fixo (datagramas) são transmitidas individualmente para destinos especificos LCMI - DAS - UFSC 8 Tipos de sockets ● ● ● 26/09/2005 TCP - Orientado a conexão – A conexão deve ser estabelecida antes da transmissão dos dados; – A conexão deve ser encerrada após a transmissão dos dados; – Em termos de qualidade de serviço da comunicação: confiável e respeita ordem FIFO. – Ex: sistema de telefonia UDP - Sem conexão – O endereço destino é especificado em cada datagrama. – Em termos de qualidade de serviço: não garante confiabilidade e nem ordenação; – Menos overhead na comunicação. – Ex: Correspondência via serviço postal O modo usado depende das necessidades da aplicação LCMI - DAS - UFSC 9 Usando Sockets em Java ● Pacote java.net; ● Principais classes: ● 26/09/2005 – TCP: Socket e ServerSocket; – UDP: DatagramPacket e DatagramSocket; – Multicast: DatagramPacket e MulticastSocket. Este pacote também contém classes que fornecem suporte a manipulação de URLs e acesso a serviços HTTP, entre outras coisas. LCMI - DAS - UFSC 10 Sockets TCP ● Clientes e servidores são diferentes. – Servidor usa a classe ServerSocket para “escutar” uma porta de rede da máquina a espera de requisições de conexão. ServerSocket sSocket = new ServerSocket(12345,5); – Clientes utilizam a classe Socket para requisitar conexão a um servidor específico e então transmitir dados. Socket cSocket = new Socket(“213.13.45.2”,12345); ● 26/09/2005 A seguir explicaremos detalhadamente como construir servidores e clientes em Java. LCMI - DAS - UFSC 11 Servidor TCP ● Inicialmente, um servidor deve criar um socket que associe o processo a uma porta do host; ServerSocket sSocket = new ServerSocket(porta,backlog); porta: número da porta que o socket deve esperar requisições; backlog: tamanho máximo da fila de pedidos de conexão que o sistema pode manter para este socket. 26/09/2005 - O backlog permite que requisições sejam enfileiradas (em estado de espera) enquanto o servidor está ocupado executando outras tarefas. - As requisições são processadas uma a uma - Se uma requisição de conexão chegar ao socket quando esta fila estiver cheia, a conexão é negada. LCMI - DAS - UFSC 12 Servidor TCP ● O método accept é usado para retirar as requisições da fila. – Fica bloqueado até que um cliente solicite uma requisição Socket socket = sSocket.accept(); ● 26/09/2005 O método accept retorna uma conexão com o cliente LCMI - DAS - UFSC 13 Servidor TCP ● ● Quando do recebimento da conexão, o servidor pode interagir com o cliente através da leitura e escrita de dados no socket. A comunicação em si é feita com o auxílio de classes tipo streams, que são classes do pacote java.io. – Stream de Leitura: DataInputStream in = new DataIntputStream(cliente.getInputStream()); Este stream tem vários métodos read (ver pacote java.io). – Stream de Escrita: DataOutputStream out = new DataOutputStream(socket.getOutputStream()); Este stream tem vários métodos write (ver pacote java.io). 26/09/2005 LCMI - DAS - UFSC 14 Servidor TCP ● Encerramento da conexão. – Com um cliente em específico: socket.close(); – Do socket servidor (terminando a associação com a porta do servidor): sSocket.close(); 26/09/2005 LCMI - DAS - UFSC 15 Servidor TCP ServerSocket serverSocket = new ServerSocket(port,backlog); do{ //aguarda conexão Socket socket = serverSocket.accept(); //obtém o stream de entrada e o encapsula DataInputStream dataInput = new DataInputStream(socket.getInputStream()); //obtém o stream de saída e o encapsula DataOutputStream dataOutput = new DataOutputStream(socket.getOutputStream()); //executa alguma coisa... no caso, um eco. String data = dataInput.readUTF(); dataOutput.writeUTF(data); //fecha o socket socket.close(); }while(notExit()); serverSocket.close(); 26/09/2005 LCMI - DAS - UFSC 16 Cliente TCP ● Inicialmente, o cliente deve criar um socket especificando o endereço e a porta do serviço a ser acessado: Socket socket = new Socket(host, porta); host é endereço ou nome do servidor porta é o número da porta em que o servidor está escutando Esta chamada representa a requisição de uma conexão com o servidor. Se o construtor for executado sem problemas, a conexão está estabelecida. ● A partir daí, da mesma forma que no servidor, o cliente pode obter os streams de entrada e saída. DataInputStream in = new DataIntputStream(cliente.getInputStream()); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); ● 26/09/2005 Ao final, o socket é fechado da mesma forma que no servidor. LCMI - DAS - UFSC 17 Cliente TCP InetAddress address = InetAddress.getbyName(name); Socket serverSocket = new Socket(address,port); //obtém o stream de saída e o encapsula DataOutputStream dataOutput = new DataOutputStream(socket.getOutputStream()); //obtém o stream de entrada e o encapsula DataInputStream dataInput = new DataInputStream(socket.getInputStream()); //executa alguma coisa... no caso, envia uma mensagem //e espera resposta. dataOutput.writeUTF(request); String response = dataInput.readUTF(); //fecha o socket socket.close(); 26/09/2005 LCMI - DAS - UFSC 18 Resumo – Sockets TCP • Servidor • Cliente – Cria o socket servidor e aguarda conexão – Usa método accept() para pegar novas conexões – Cria streams entrada/saída para o socket da conexão – Faz a utilização dos streams conforme o protocolo – Fecha os streams – Fecha socket da conexão – Repete várias vezes – Fecha o socket servidor 26/09/2005 – Cria o socket com conexão cliente – Associa streams de leitura e escrita com o socket – Utiliza os streams conforme o protocolo do servidor – Fecha os streams – Fecha o socket LCMI - DAS - UFSC 19 Resumo – Sockets TCP Cliente Servidor Inicia aplicação Cria o socket servidor Cria o socket Tentativa de conexão Aceita conexão Cria streams Conduz conversa Troca de dados Cria streams Conduz conversa Fecha streams e socket Desconexão Fecha streams e socket Termina aplicação 26/09/2005 LCMI - DAS - UFSC Não mais Sim 20 Resumo – Sockets TCP ● ● 26/09/2005 Servidor apresentado processa uma conexão de cada vez Servidor concorrente – Cria uma nova thread para cada conexão aberta – Consegue processar várias conexões simultaneamente LCMI - DAS - UFSC 21 Sockets UDP ● A comunicação UDP é feita através de duas classes: – A mesma classe é usada pelo cliente e pelo servidor – Classe DatagramSocket: ● Socket servidor: DatagramSocket socket = new DatagramSocket(porta); O servidor deve especificar sua porta. Omissão próxima porta livre. ● – Socket cliente: DatagramSocket socket = new DatagramSocket(); Classe DatagramPacket ● ● As comunicações ocorrem através da troca de datagramas Os datagramas contêm: – – 26/09/2005 os dados a serem enviados e recebidos endereço de destino/origem do datagrama. LCMI - DAS - UFSC 22 Servidor UDP ● ● Inicialmente o servidor deve criar um socket que o associe a uma porta da máquina. – DatagramSocket socket = new DatagramSocket(porta); – porta: número da porta que o socket deve esperar requisições; Depois do socket criado, o servidor fica bloqueado até o recebimento de um datagrama (método receive) byte[] buffer = new byte[n]; \\{array de bytes} DatagramPacket dg = new DatagramPacket(buffer,n); socket.receive(dg); – ● 26/09/2005 Os dados recebidos devem caber no buffer do datagrama. Desta forma, protocolos mais complexos baseados em datagramas devem definir cabeçalhos e mensagens de controle. Fechamento do socket: socket.close(); LCMI - DAS - UFSC 23 Servidor UDP ● Para enviar dados para um socket datagrama – – ● Necessário um endereço, classe InetAddress InetAddress addr = InetAddress.getByName(“alambique.das.ufsc.br”); O envio de datagramas é realizado de forma bastante simples: String toSend = “Este eh o dado a ser enviado!”; byte data[] = toSend.getBytes(); DatagramPacket sendPacket = new DatagramPacket(data,data.length,host,porta); socket.send(sendPacket); ● A String deve ser convertida para array de bytes. ● Endereço destino (host + porta ) é incluído no DatagramPacket. ● Como saber quem enviou o pacote ? – – 26/09/2005 pacoteRecebido.getAddress(); pacoteRecebido.getPort(); LCMI - DAS - UFSC 24 Servidor UDP DatagramSocket socket = new DatagramSocket(port); do{ //recebimento dos dados em um buffer de 1024 bytes DatagramPacket recPacket = new DatagramPacket( new byte[1024],1024); socket.receive(recPacket); //recepção //envio de dados para o emissor do datagrama recebido DatagramPacket sendPacket = new DatagramPacket( recPacket.getData(),recPacket.getData().length, recPacket.getAddress(),recPacket.getPort()); socket.send(sendPacket); //envio }while(notExit()); socket.close(); 26/09/2005 LCMI - DAS - UFSC 25 Cliente UDP ● Inicialmente o cliente deve criar um socket. DatagramSocket socket = new DatagramSocket(); ● Opcional: o cliente pode conectar o socket a um servidor específico, de tal forma que todos os seus datagramas enviados terão como destino esse servidor. socket.connect(host,porta); Parâmetros: host é endereço ou nome do servidor e porta é o número da porta em que o servidor espera respostas. Executando o connect, o emissor não necessita mais definir endereço e porta destino para cada datagrama a ser enviado. ● 26/09/2005 A recepção e o envio de datagramas, bem como o fechamento do socket, ocorrem da mesma forma que no LCMI - DAS - UFSC 26 Cliente UDP InetAddress address = InetAddress.getByName(name); DatagramSocket socket = new DatagramSocket(); //socket.connect(address,port); byte[] req = ... //envio de dados para o emissor do datagrama recebido DatagramPacket sendPacket = new DatagramPacket(req,req.length,address,port); //DatagramPacket dg1 = new DatagramPacket(req,req.length); socket.send(sendPacket); //envio //recebimento dos dados em um buffer de 1024 bytes DatagramPacket recPacket = new DatagramPacket( new byte[1024],1024); socket.receive(recPacket); //recepção byte[] resp = recPacket.getData(); socket.close(); 26/09/2005 LCMI - DAS - UFSC 27 Resumo – Sockets UDP • Cliente • Servidor – Cria um socket datagrama em qualquer porta livre – Cria um endereço destinatário – Envia os dados conforme o protocolo em questão – Espera por dados com a resposta – Repete várias vezes – Fecha o socket datagrama 26/09/2005 – Cria um socket datagrama em uma porta específica – Chama receive() para esperar por pacotes – Responde ao pacote recebido conforme protocolo em questão – Repete várias vezes – Fecha o socket LCMI - DAS - UFSC 28 Resumo – Sockets UDP Cliente Cria o socket datagrama Envia dados (solicitação) Recebe dados Servidor Inicia aplicação Dados do Cliente Dados do Servidor Cria o socket datagrama Recebe dados Envia dados (resposta) Não Fim? Fim? Sim Sim Fecha socket 26/09/2005 Não Termina aplicação LCMI - DAS - UFSC Fecha socket 29 Sockets Multicast ● ● 26/09/2005 Por ser um modelo baseado em datagramas a programação baseada em UDP/Multicast IP não difere muito da programação UDP já vista. As duas principais diferenças, em termos de modelo de programação, são: – Uso da classe MulticastSocket (ao invés de DatagramSocket). A classe MulticastSocket estende a classe DatagramSocket ( os métodos da segunda estão disponíveis na primeira); – Servidores interessados em receber mensagens de um grupo devem entrar nesse grupo. LCMI - DAS - UFSC 30 Revisão: Multicast IP ● ● ● ● ● 26/09/2005 Extensões ao protocolo IP para comunicação multiponto; Assim como o IP “unicast”, não oferece garantias a respeito da entrega ou ordenação de pacotes; Cada grupo é identificado por um endereço IP classe D (224.0.0.0 a 239.255.255.255); Define grupos abertos e não provê informações sobre quem são os membros (membership); O gerenciamento de grupos é feito de maneira dinâmica através de operações implementadas pelo IGMP (Internet Group Management Protocol). LCMI - DAS - UFSC 31 Sockets Multicast ● Operações para gerenciamento de grupos: – CreateGroup: Cria um grupo cujo único membro é o host criador; – Executa quando um primeiro servidor se junta a um grupo. JoinGroup: Requisita a adição deste host a um grupo existente; MulticastSocket socket = new MulticastSocket(porta); socket.joinGroup(groupAddress); – LeaveGroup: Pede a remoção do host invocador ao grupo especificado. socket.leaveGroup(groupAddress); ● 26/09/2005 Operações para envio e recepção de grupos: socket.send(dg) ou socket.receive(dg). LCMI - DAS - UFSC 32 Servidor Multicast IP InetAddress groupAddress = InetAddress.getByName(“226.1.1.1”); MulticastSocket socket = new MulticastSocket(port); socket.joinGroup(groupAddress); do{ //recebimento dos dados em um buffer de 1024 bytes DatagramPacket dg = new DatagramPacket( new byte[1024],1024); socket.receive(dg); //recepção //imprime a mensagem recebida System.out.println(“received ”+ new String(dg.getData).trim()); }while(notExit()); socket.leaveGroup(groupAddress); socket.close(); 26/09/2005 LCMI - DAS - UFSC 33 Cliente Multicast IP String message = ... InetAddress groupAddress = InetAddress.getByName(“226.1.1.1”); MulticastSocket socket = new MulticastSocket(); byte[] data = message.getBytes(); //recebimento dos dados em um buffer de 1024 bytes DatagramPacket dg = new DatagramPacket( data,data.length,0,groupAddres,port); socket.send(dg); //envio socket.close(); 26/09/2005 LCMI - DAS - UFSC 34 Referências ● ● ● Sockets em Java – http://java.sun.com/docs/books/tutorial/networking/index.html – http://java.sun.com/developer/technicalArticles/ALT/sockets/ Sockets em C – http://www.cs.rpi.edu/courses/sysprog/sockets/sock.html – http://www.scit.wlv.ac.uk/~jphb/comms/sockets.html Esta apresentação e exemplo de cada tipo de sockets em: – 26/09/2005 www.das.ufsc.br/~fabio/sockets/ LCMI - DAS - UFSC 35 26/09/2005 LCMI - DAS - UFSC 36