Você está na página 1de 9

Java : Comunicao Cliente-Servidor.

Objetivo:
Capacitar o aluno a desenvolver uma aplicao servidora para mltiplos
clientes.
Apresentar as classes Socket e ServerSocket, classes de fluxo de dados,
a classe Thread, a interface Runnable e a classe Vector.
Apresentar, tambm, a prtica de definio de protocolos de comunicao.

Sumrio

Introduo ............................................................................................................... 2
1. Threads ............................................................................................................... 2
A classe Thread...................................................................................................... 2
Exemplo de Thread ................................................................................................ 2
Inicializao da Thread: .......................................................................................... 2
Exemplo de chamada de duas Threads:..................................................................... 2
Comentrios: ......................................................................................................... 3
2. As Classes Socket e ServerSocket ..................................................................... 4
O que um Socket? ................................................................................................ 4
A classe Socket: ..................................................................................................... 4
A classe ServerSocket:............................................................................................ 4
Exemplo de Servidor com ServerSocket e Socket: ................................................... 4
Exemplo de Cliente ................................................................................................ 8

Prof. Vida (vida@utfpr.edu.br)


1

Introduo
Uma aplicao servidora deve ser capaz de fornecer servios a clientes que se
conectem a ela. Atravs de uma rede TCP/IP, um servidor gerencia uma porta de
entrada. O TCP/IP um conjunto de protocolos desenvolvido de modo a permitir que
computadores compartilhem recursos atravs da rede. Qualquer cliente que queira
acessar os servios de uma aplicao, o faz atravs dessa porta de entrada.
O servidor necessita, constantemente, verificar na porta se algum cliente est
solicitando um servio. Essa ao pode ser realizada em Java, atravs da classe Thread
ou da interface Runnable. Threads e Runnables so executadas de forma concorrente
com o sistema operacional e outras aplicaes.
Uma Thread ou Runnable possuem a assinatura de mtodo public void
run(). Quando disparada, tanto a Thread quanto a Runnable, executam esse mtodo
de forma concorrente com os outros servios do sistema operacional.

1. Threads
A classe Thread

A classe Thread permite definir um servio no sistema


operacional. A Java Virtual Machine permite que uma aplicao
possua diversos servios sendo executadas de forma
concorrente. No exemplo abaixo, a classe Servidor extende essa
classe Thread.

Exemplo de Thread /*01*/ ///////// arquivo Servidor.java


/*02*/ public class Servidor extends Thread
/*03*/ {
/*04*/
int i=0;

Inicializao da
Thread:

/*05*/
/*06*/
/*07*/
/*08*/
/*09*/
/*10*/
/*11*/

public void run()


{
while(true)
{
System.out.print("\r"+(++i));
}
}

/*12*/
/*13*/
/*14*/
/*15*/

public static void main(String[] a)


{ Servidor s = new Servidor();
s.start(); //disparo da Thread
} }

A inicializao da Thread feita atravs da chamada do mtodo


start(), conforme exemplificado na linha 14 do cdigo anterior.
Essa instruo ir executar o servio definido no mtodo public
void run() .

Exemplo de /*01*/ ///////// arquivo Servidor.java


chamada de duas /*02*/ public class Servidor extends Thread {
int i=0;
Threads: /*03*/
/*04*/
int espera=0;
/*05*/
/*06*/

public Servidor(String n,int tempo)


{setName(n);espera=tempo;}

/*07*/

public void run()

Prof. Vida (vida@utfpr.edu.br)


2

/*08*/
/*09*/
/*10*/
/*11*/
/*12*/
/*13*/
/*14*/
/*15*/
/*16*/
/*17*/
/*18*/
/*19*/
/*20*/
Comentrios:

{
{

while(true)
System.out.print("\r" + getName()
+":" + (++i));
try {sleep(espera);}
catch (InterruptedException erro){}
} }

public static void main(String[] a)


{ Servidor s = new Servidor("contador",1000);
s.start();
Servidor s2 = new Servidor("cont",100);
s2.start();
} }

O primeiro exemplo, o arquivo Servidor.java, foi modificado.


Nessa modificao, a funo sleep( milisegundos )
inserida ao cdigo. Essa funo permite que a Thread adormea. Esse
tempo de espera fornecido no construtor, bem como um nome para a
Thread.
Um destaque deve ser dado necessidade da estrutura try ...
catch (InterruptedException).
O mtodo main inicializa dois servios, s e s2, conforme
exemplificam as linhas 16 a 19 do cdigo anterior.
A figura abaixo ilustra um snapshot da execuo.

A Thread instanciada por s, possui o nome contador e o tempo de


espera de 1000 milisegundos. Cada execuo dessa Thread, o nome da
thread impresso, um valor incrementado tambm impresso e uma
espera de 1000 milisegundos disparada.
A instncia s2, por outro lado, possui o tempo de espera de 100
milisegundos e o seu nome cont. Ela imprime o seu nome e outro
valor incrementado e impresso.
Observe que o caracter \r na instruo System.out.print,
faz com que essas impresses sejam sobrepostas.
Logo, a thread s2 executado mais vezes que a thread s.

Prof. Vida (vida@utfpr.edu.br)


3

2. As Classes Socket e ServerSocket


Um Socket uma combinao de um computador com o nmero da

O que um porta. Essa combinao identifica uma porta de entrada para uma
Socket? aplicao.

Classe que implementa um cliente socket. Um socket o ponto

A classe Socket: final da comunicao entre duas mquinas.

Classe que implementa um servidor de socket. Um servidor de

A classe sockets espera pela solicitao de usurios da rede de computador.. Ele


ServerSocket: executa algumas operaes baseadas na solicitao recebida e retorna

valores.
Dos mtodos disponveis, o principal o construtor. Nele definido
a porta de leitura. Linhas 8 e 20 do cdigo abaixo.

/*1*/ /////////////////////// arquivo


Exemplo de /*2*/ import java.io.*;
Servidor com /*3*/ import java.net.*;
/*4*/ import java.util.*;

ServerSocket e
Socket: /*5*/
/*6*/
/*7*/
/*8*/
/*9*/

/*10*/
/*11*/
/*12*/
/*13*/
/*14*/
/*15*/
/*16*/

public class
{
private
private
private

Servidor.java

Servidor extends Thread

int porta;
ServerSocket ouvido;
ObjectOutputStream output;
// fluxo de saida de dados.
private ObjectInputStream inStream;
// fluxo de entrada de dados.
private Vector listaJogador = new Vector();
private Jogador visitante;

public void conecta(int porta)


{
// armazena o numero da porta em uma
// variavel denomiada por "porta"
/*17*/
this.porta = porta;
/*18*/
try
/*19*/
{
/*20*/
ouvido = new java.net.ServerSocket(porta);
// tenta se conectar com a porta.
/*21*/
}
/*22*/
catch(java.io.IOException e)
{e.printStackTrace(); System.exit(1);}
// se deu erro, entao encerre a aplicao.
/*23*/
/*24*/
System.out.println(
"Servidor no ar na porta " + porta + " !!");
// se no deu erro, informe que o servidor est no ar
// na porta definida.
/*25*/
}
/*26*/
/*27*/
public Servidor(String n,int gate)
/*28*/
{setName(n);
/*29*/
conecta(gate);
/*30*/
}
/*31*/
/*32*/
public void run()
/*33*/
{

Prof. Vida (vida@utfpr.edu.br)


4

/*34*/
/*35*/
/*36*/
/*37*/
/*38*/

while(true)
{
try
{
// servidor.accept() => espera por um
//cliente , quando o cliente solicita
//conexao,
// uma instancia da classe Jogador eh
// criada para representar essa conexao.

/*39*/
/*40*/
/*41*/
/*42*/
/*43*/
/*44*/
/*45*/
/*46*/
/*47*/
/*48*/
/*49*/
/*50*/
/*51*/
/*52*/
/*53*/
/*54*/
/*55*/
/*56*/
/*57*/
/*58*/
/*59*/
/*60*/
/*61*/
/*62*/
/*63*/
/*64*/
/*65*/
/*66*/
/*67*/
/*68*/
/*69*/
/*70*/
/*71*/
/*72*/
/*73*/
/*74*/
/*75*/
/*76*/
/*77*/
/*78*/
/*79*/
/*80*/
/*81*/
/*82*/

visitante =new Jogador(ouvido.accept());


visitante.start();
addJogador(visitante);
visitante.informe(
"Bem Vindo a porta : "+porta);
visitante.informe("[nome?]");
} catch (java.io.IOException e) {}
}
}
public static void main(String[] a)
{ Servidor s = new
Servidor("contador",5555);
s.start();
Servidor s2 = new
Servidor("cont",6666);
s2.start();
}
private void removeJogador(Jogador j)
{
listaJogador.remove(j);
}
// adiciona um jogador na lista de jogadores.
private void addJogador (Jogador j)
{
listaJogador.add(j);
}
//////////////definiao interna de classe
class Jogador extends Thread{
private ObjectOutputStream output;
// fluxo de saida de dados.
private ObjectInputStream inStream;
// fluxo de entrada de dados.
private Socket connection;
// armazena ponteiro para o servidor.
private boolean noAr=true;
private String nome="";
// construtor da classe
public Jogador(Socket s)
{
connection=s;
// armazena a conexao com o servidor.
try{
output = new
ObjectOutputStream(s.getOutputStream());
// cria fluxo de saida de dados.

Prof. Vida (vida@utfpr.edu.br)


5

/*83*/

inStream = new
ObjectInputStream(s.getInputStream());
// cria fluxo de entrada de dados.
output.flush(); // limpa o Buffer.
}
catch (IOException e) {}
}

/*84*/
/*85*/
/*86*/
/*87*/
/*88*/
/*89*/
public void run()
/*90*/
{ String fofoca;
/*91*/
int x;
/*92*/
while(noAr)
/*93*/
{
/*94*/
fofoca=ouvir(false);
/*95*/
x = fofoca.indexOf("bye");
// se o cliente enviou a instrucao para desconectar-se
// do servidor, x armazenarah um valor superior a
// (-1).
/*96*/
if ( x >= 0)
/*97*/
{this.noAr=false;this.interrupt();
/*98*/
Servidor.this.removeJogador(this);
/*99*/
System.out.println(
"Pedido de excluso recebido!");
/*100*/
informe("[exit]");
// informa ao cliente que ele foi desconectado
/*101*/
continue;
/*102*/
}
/*103*/
if ( fofoca.indexOf("[nome?]") > -1)
/*104*/
{nome = fofoca.substring(7);}
/*105*/
if ( fofoca.indexOf("[conte mais]") > -1)
/*106*/
{System.out.println("Recebi de " + nome + ":"
+ fofoca.substring(12)); }
/*107*/
informe("[conte mais]");
/*108*/
}
/*109*/
}
/*110*/ // foram definidos os seguintes protocolos de
// comunicacao: [nome?], [conte mais], [exit].
/*111*/
/*112*/
/*113*/
/*114*/
/*115*/
/*116*/
/*117*/
/*118*/
/*119*/
/*120*/
/*121*/
/*122*/
/*123*/

/*124*/
/*125*/
/*126*/
/*127*/
/*128*/

// envia mensagens aos jogadores clientes.


private void informe(String m)
{
try
{
output.writeObject(m);
output.flush();
}
catch (java.io.IOException e)
{
System.out.println(
"Erro de envio de mensagem");
this.closeConnection();
noAr=false;
// se um erro acontecer, entao desconectar o
// jogador e desligar a Thread. A Thread eh
// ligada com a instrucao interrupt().
}
}
// rotina de recebimento de mensagens do
// servidor
private String ouvir(boolean eco)

Prof. Vida (vida@utfpr.edu.br)


6

/*129*/
/*130*/
/*131*/
/*132*/

{
String saida = new String("");
try {
saida =
String.valueOf(inStream.readObject());
if (eco) System.out.println("ouvi " +
saida);}
catch (IOException e )
{ saida = "";}
catch (java.lang.ClassNotFoundException
clerr)
{ System.out.println(clerr);}
catch (NullPointerException err){}

/*133*/
/*134*/
/*135*/
/*136*/
/*137*/
/*138*/
/*139*/
/*140*/
/*141*/
/*142*/
/*143*/
/*144*/
/*145*/
/*146*/
/*147*/
/*148*/
/*149*/
/*150*/
/*151*/
/*152*/
/*153*/
/*154*/
/*155*/
/*156*/

return saida;
}
// rotina que permite retirar o jogador da lista
// de jogadores e desconecta-lo do servidor.
private void closeConnection()
{
try
{Servidor.this.removeJogador(this);
if (this.isAlive())
{ this.interrupt();
// encerra a Thread.
connection.close();}
}
catch (Exception exp)
{System.out.println("Cliente ausente");}
}
}
// fim da classe interna.
////////////////////////////
} // fim da classe Servidor

Prof. Vida (vida@utfpr.edu.br)


7

/*1*/ /////////////////// arquivo cliente.java


/*2*/
import java.io.*;
Exemplo de
/*3*/
import
java.net.*;
Cliente
/*4*/ import java.util.*;
/*5*/ import javax.swing.*;
/*6*/ class ConversaServidor implements Runnable
/*7*/ {
/*8*/
private Socket con ;
/*9*/
private ObjectOutputStream output;
/*10*/ private ObjectInputStream
input;
/*11*/ private int p; // porta a ser conectado.
/*12*/
/*13*/ // o construtor cria e abre uma conexao com o
// servidor.
/*14*/
/*15*/
/*16*/
/*17*/
/*18*/
/*19*/
/*20*/
/*21*/
/*22*/
/*23*/
/*24*/
/*25*/
/*26*/
/*27*/
/*28*/
/*29*/
/*30*/
/*31*/
/*32*/
/*33*/
/*34*/
/*35*/
/*36*/
/*37*/
/*38*/
/*39*/
/*40*/
/*41*/
/*42*/
/*43*/
/*44*/
/*45*/
/*46*/
/*47*/

public ConversaServidor(String endereco


, int porta)
// recebe o endereco e porta como parametros.
{
try
{
con = new
Socket(InetAddress.getByName(endereco),porta );
output = new
ObjectOutputStream(con.getOutputStream());
InputStream s = con.getInputStream();
input = new ObjectInputStream(s);
}
catch(java.io.IOException er1)
{System.out.println(er1.getMessage());}
}
// metodo que eh executado quando a Thread eh
// iniciada - metodo start().
public void run()
{
String texto="";
String mens="";
while(true)
{
try
{
mens = (String)input.readObject();
// li algo do servidor.
if (mens.length() > 1)
{
System.out.println("Recebi do
+ servidor:"+mens);
if (mens.lastIndexOf("[nome?]") > -1)
{texto = "Identifique-se, por favor...";
mens="[nome?]";
System.out.println("Pedido de indentificao
+ feito pelo servidor.");
}
if (mens.lastIndexOf("[conte mais]") > -1)
{texto = "Mande-me alguma informao";
mens="[conte mais]";
System.out.println(
"Pedido de mais informacao.");
}

Prof. Vida (vida@utfpr.edu.br)


8

/*48*/

if (mens.lastIndexOf("[exit]")>-1)
{System.exit(0);}
if (texto.length() > 0)
//repete o protocolo e envia um texto digitado.
sendData(mens
+JOptionPane.showInputDialog(texto));
mens="";texto=""; //limpa tudo
}
}
catch (java.io.OptionalDataException e)
{System.out.println(
"Erro no desconectar.\n"
+e.getMessage());}
catch (java.lang.ClassNotFoundException e)
{System.out.println("Class not found. \n"+
e.getMessage());}
catch (java.io.IOException e)
{System.out.println("Erro de IO. \n"+
e.getMessage());}
}

/*49*/

/*50*/
/*51*/
/*52*/
/*53*/

/*54*/
/*55*/
/*56*/
/*57*/
/*58*/
/*59*/
/*60*/
/*61*/
/*62*/
/*63*/
/*64*/
/*65*/
/*66*/
/*67*/
/*68*/
/*69*/
/*70*/
/*71*/
/*72*/
/*73*/
/*74*/
/*75*/
/*76*/
/*77*/
/*78*/

}
// envia mensagens ao servidor.
public void sendData(String m)
{
try{ output.writeObject(m);
output.flush(); // limpa o bbuffer.
}
catch (IOException e) {System.out.println(
"Nao foi possivel enviar os dados.\n"
+ e.getMessage());}
}
}
public class cliente extends ConversaServidor
{
public cliente(int porta)
{super("127.0.0.1",porta);}
public static void main(String[] a)
{
cliente c1 = new cliente(5555);
c1.run();
}
}

Prof. Vida (vida@utfpr.edu.br)


9