Você está na página 1de 6

Usando Sockets

Sockets. O que so, pra que servem e como funcionam A estrutura Socket foi uma inovao apresentada pelo sistema Berkeley Unix. Atravs desta estrutura, o programador por ler e gravar bytes como uma stream qualquer de dados. Alm disto, esconde os detalhes de baixo nvel das redes tais como tipo de transmisso, tamanho de pacote, retransmisso e etc. Atravs de um socket podemos realizar vrias operaes, como exemplo: Estabelecer conexes entre mquinas Enviar e receber dados Encerrar conexes Esperar por conexes em determinada porta

O socket na verdade um elemento de software que prov uma interface de rede para a aplicao. Vamos tratar dos sockets TCP, porm Java permite a utilizao de sockets UDP e fornece meios para que voc possa utilizar outros tipos no definidos atravs da classe SocketImpl e da interface SocketImplFactory. Onde esto? Quem so? Os sockets esto localizados no pacote java.net. Basicamente precisamos das classes Socket e ServerSocket para conseguir implementar uma aplicao bsica. A classe Socket implementa o socket cliente. Para construir um socket precisamos saber qual o IP que desejamos conectar e a porta de conexo (que varia de 0 a 65535). A classe ServerSocket fornece a interface de rede necessria para que a aplicao possa funcionar como um servidor TCP. Para criar um ServerSocket precisamos saber qual a porta que ser utilizada. Comumente utiliza-se portas acima de 1000 pois as inferiores so utilizadas pelo sistema operacional. Mos obra Para ilustrar o uso dos sockets, iremos construir uma aplicao bastante simples para comunicao de dois computadores. Um computador ficar aguardando alguma conexo e ir exibir em tela o que foi recebido. Veremos ento a classe Servidor e a classe Cliente.
import import import import import java.io.BufferedReader; java.io.IOException; java.io.InputStreamReader; java.net.ServerSocket; java.net.Socket;

public class Servidor { public static void main(String[] args) { //Declaro o ServerSocket ServerSocket serv=null; //Declaro o Socket de comunicao Socket s= null; //Declaro o leitor para a entrada de dados BufferedReader entrada=null; try{

//Cria o ServerSocket na porta 7000 se estiver disponvel serv = new ServerSocket(7000); //Aguarda uma conexo na porta especificada e cria retorna o socket que ir comunicar com o cliente s = serv.accept(); //Cria um BufferedReader para o canal da stream de entrada de dados do socket s entrada = new BufferedReader(new InputStreamReader(s.getInputStream())); //Aguarda por algum dado e imprime a linha recebida quando recebe System.out.println(entrada.readLine()); //trata possveis excesses de input/output. Note que as excesses so as mesmas utilizadas para as classes de java.io }catch(IOException e){ //Imprime uma notificao na sada padro caso haja algo errado. System.out.println("Algum problema ocorreu para criar ou receber o socket."); }finally{ try{ //Encerro o socket de comunicao s.close(); //Encerro o ServerSocket serv.close(); }catch(IOException e){ } }

Vamos explicar os pontos importantes da classe acima. No techo


//Declaro o ServerSocket ServerSocket serv=null; //Declaro o Socket de comunicao Socket s= null; //Declaro o leitor para a entrada de dados BufferedReader entrada=null;

apenas declaramos as variveis que iremos utilizar. Na trecho


//Cria o ServerSocket na porta 7000 se estiver disponvel serv = new ServerSocket(7000);

, criamos o server socket na porta 7000.

No trecho
//Aguarda uma conexo na porta especificada e cria retorna o socket que ir comunicar com o cliente s = serv.accept();

utilizamos o mtodo accept() que espera por uma conexo e continua somente quando recebe uma. Ento retorna um socket para comunicar com o cliente que acaba de se conectar. O mtodo accept() do ServerSocket, quando invocado, faz com que a Thread atual seja "paralisada" at que uma conexo seja recebida. comum, em ambientes reais, lanarmos uma Thread a cada conexo recebida pelo ServerSocket. Isto feito para que possamos tratar vrios clientes conectados simultaneamente. Veremos como fazer isto em um outro tutorial. No trecho
//Cria um BufferedReader para o canal da stream de entrada de dados do socket s entrada = new BufferedReader(new InputStreamReader(s.getInputStream()));

criamos um leitor dos dados de entrada baseado no canal de entrada de dados do socket. O BufferedReader l texto de uma text-input stream e os deixa em buffer para leitura eficiente das informaes. O InputStreamReader l os bytes que esto chegando e os transforma em caracteres para que o BufferedReader possa entender. No trecho
//Aguarda por algum dado e imprime a linha recebida quando recebe System.out.println(entrada.readLine());

chamamos o mtodo readline() da classe BufferedReader. Atravs deste mtodo, o programa aguarda a chegada de algum dado no canal de entrada e l uma linha. Aps linha ser recebida ela impressa na sada padro do sistema com o popular System.out.println(). Nas linhas
//Encerro o socket de comunicao s.close(); //Encerro o ServerSocket serv.close();

, fechamos os sockets. Note que fizemos isto dentro de um bloco do tipo finally pois isto garante que os recursos sero liberados. muito importante liberar este tipo de recurso sempre que no forem mais necessrios, pois so finitos e representam um custo considervel de manuteno. Mos Obra - Continuando...

Agora vejamos a classe Cliente.

import java.io.IOException; import java.io.PrintStream; import java.net.Socket; public class Cliente { public static void main(String[] args) { //Declaro o socket cliente Socket s = null; //Declaro a Stream de saida de dados PrintStream ps = null; try{ //Cria o socket com o recurso desejado na porta especificada s = new Socket("127.0.0.1",7000); //Cria a Stream de saida de dados ps = new PrintStream(s.getOutputStream()); //Imprime uma linha para a stream de sada de dados ps.println("Estou enviando dados para o servidor"); //Trata possveis excees }catch(IOException e){ System.out.println("Algum problema ocorreu ao criar ou enviar dados pelo socket."); }finally{ try{ //Encerra o socket cliente s.close(); }catch(IOException e){} } } }

Nas linhas
//Declaro o socket cliente Socket s = null; //Declaro a Stream de saida de dados PrintStream ps = null;

apenas declaramos as variveis que iremos utilizar. Na linha


//Cria o socket com o recurso desejado na porta especificada

s = new Socket("127.0.0.1",7000);

criamos o socket. De acordo com o construtor que utilizamos, criamos um socket para comunicao com o IP 127.0.0.1 (IP LoopBack*) na porta 7000 (que a porta que nosso servidor ir escutar. Na linha
//Cria a Stream de saida de dados ps = new PrintStream(s.getOutputStream());

criamos um objeto do tipo PrintStream para poder imprimir dados para o canal de sada do socket. Na linha
//Imprime uma linha para a stream de sada de dados ps.println("Estou enviando dados para o servidor");

utilizamos o mtodo println() da classe PrintStream para imprimir uma String que ser enviada atravs do socket para o Servidor. O mtodo println() da classe PrintStream converte os caracteres digitados para o formato adequado de envio atravs do socket. Verifique a especificao da API para verificar todos os tipos de dados que podem ser impressos por este mtodo. Na linha
//Encerra o socket cliente s.close();

fechamos o socket dentro do bloco finally. Agora, que entendemos o cdigo podemos execut-los Copie os arquivos do tutorial para uma pasta e compile-os da forma comum. javac Servidor.java javac Cliente.java Agora, abra 2 janelas de prompt. Vamos executar cada classe em um prompt diferente (para testar em um mesmo equipamento). Em uma das janelas digite java Servidor e na outra digite java Cliente. Voc dever perceber que ao executar a classe Cliente, o texto Estou enviando dados para o servidor ser exibido na janela da classe Servidor. Pronto, esta a nossa aplicao funcionando em rede de forma simples. Faa testes, verifique o que acontece quando o servidor no est rodando, altere os Ips caso esteja em rede, ou se estiver conectado a internet teste com seus amigos, leia a especificao das APIs e, quem sabe, adicionar recursos... Demos o passo inicial, agora com voc!

*IP LoopBack Termo utilizado para representar uma forma de comunicao com o prprio equipamento (geralmente utilizado para efetuar testes). Para acess-lo, utilizamos 127.0.0.1 ou simplesmente localhost.