Pesquisar no Programero

sábado, 24 de maio de 2008

Interação Cliente/Servidor sem Conexão com Datagramas (Java)

A transmissão sem conexão com datagramas é parecida com a maneira como a correspondência é transportada através do serviço postal. Se uma mensagem grande não couber em um envelope, você a divide em partes de mensagem separadas que você coloca em envelopes separados, numerados seqüencialmente. Cada uma das cartas é, então, remetida ao mesmo tempo. As cartas podem chegar em ordem, fora da ordem, ou não chegar (pouco provável). O receptor monta novamente os pedaços da mensagem na ordem seqüencial antes de tentar dar sentido a mensagem. Se a mensagem é suficientemente pequena para caber em um envelope, não há necessidade de se preocupar com a questão seqüencial.

A classe Servidor
A classe Server_D define dois DatagramPackets que o servidor utiliza para enviar e receber informações e um DatagramSocket que envia e recebe esses pacotes. O construtor para a classe Server_D cria a interface gráfica com o usuário na qual os pacotes de informação serão exibidos. Em seguida, o construtor cria o DatagramSocket em um bloco try. O construtor DatagramSocket recebe um argumento de numero de porta inteiro (5000) para vincular o servidor a uma porta em que o servidor pode receber pacotes de clientes. Os Clientes que enviam pacotes para esse servidor especificam a porta 5000 nos pacotes enviados. O construtor DatagramSocket dispara um SocketException se não conseguir vincular o DatagramSocket a uma porta.
package PKJServer_D;

//pacotes de nucleo do java
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;

//pacotes de extenção
import javax.swing.*;

public class Server_D extends JFrame{
private JTextArea displayArea;
private DatagramPacket sendPacket, receivePacket;
private DatagramSocket socket;

//configura a GUI e o DatagramSocket
public Server_D()
{
super("Servidor");
displayArea = new JTextArea();
getContentPane().add( new JScrollPane( displayArea ), BorderLayout.CENTER );
setSize( 400, 300 );
setVisible( true );

//cria DatagramSocket para enviar e receber pacotes
try
{
socket = new DatagramSocket( 5000 );
}

//processa problemas ocorridos na criação do datagramSocket
catch( SocketException socketException )
{
socketException.printStackTrace();
System.exit( 1 );
}

}//fim do construtor Server_D

//espera que os pacotes cheguem e, depois,
//exibe os dados e ecoa o pacote para o cliente
public void waitForPackets()
{
//repete laço pra sempre
while( true )
{
try
{
//recebe o pacote
byte data[] = new byte[100];
receivePacket = new DatagramPacket( data, data.length );

//espera o pacote
socket.receive( receivePacket );

//processa o pacote
displayPacket();

//ecoa as informações
sendPacketToClient();

}
//processa problemas ocorridos na manipulação do pacote
catch( IOException ioException )
{
displayArea.append( ioException.toString() + "\n" );
ioException.printStackTrace();
}
}//fim do while

//processa problemas
}//fim do metodo waitForPackets

//exibe o conteudo do pacote
private void displayPacket()
{
displayArea.append( "\nPacote Recebido:" +
"\ndo Host: " + receivePacket.getAddress() +
"\nPorta do Host: " + receivePacket.getPort() +
"\nTamanho: " + receivePacket.getLength() +
"\nContendo:\n\t" +
new String( receivePacket.getData(), 0, receivePacket.getLength() )
);
}

//ecoa pacote para o cliente
private void sendPacketToClient() throws IOException
{
displayArea.append( "\n\nEnviando para o Cliente..." );

//cria pacote para enviar
sendPacket = new DatagramPacket( receivePacket.getData(),
receivePacket.getLength(),
receivePacket.getAddress(),
receivePacket.getPort()
);
//envia pacote
socket.send( sendPacket );

displayArea.append( "Pacote Enviado\n" );
displayArea.setCaretPosition( displayArea.getText().length() );
}

//executa o aplicativo
public static void main(String[] args)
{
Server_D application = new Server_D();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
application.waitForPackets();

}

}//fim da classe Server_D

A classe Cliente
A classe Client_D funciona de maneira semelhante a classe Server_D, com a diferença que o cliente envia pacotes apenas quando o usuário digita uma mensagem no JTextField e pressiona a tecla Enter. Quando isso ocorre, o programa chama o método actionPerformed, que converte o String que o usuário digitou no JTextField em um array de byte. È criado um DatagramPacket inicializado com um array de byte, o comprimento do String digitado pelo usuário, o endereço da internet para o qual o pacote deve ser enviado (InetAddress.getLocalHost()) e o numero da porta em que o servidor esta esperando os pacotes.

package PKJClient_D;

//pacotes de nucleo do java
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;

//pacotes de extenção
import javax.swing.*;

public class Client_D extends JFrame{
private JTextField enterField;
private JTextArea displayArea;
private DatagramPacket sendPacket, receivePacket;
private DatagramSocket socket;

//configura a GUI e o DatagramSocket
public Client_D()
{
super( "Cliente" );
Container container = getContentPane();
enterField = new JTextField( "Digite a Mensagem aqui" );
enterField.addActionListener(
new ActionListener()
{
//cria e envia pacote
public void actionPerformed( ActionEvent event )
{
//cria e envia pacote
try
{
displayArea.append( "\nEnviando o Pacote contendo: " +
event.getActionCommand() + "\n");
//obtém mensagem do campo de texto e a converte
//para um array de bytes
String message = event.getActionCommand();
byte data[] = message.getBytes();

//cria sendPacket
sendPacket = new DatagramPacket(
data, data.length, InetAddress.getLocalHost(), 5000 );

//envia pacote
socket.send( sendPacket );

displayArea.append( "Pacote enviado\n" );
displayArea.setCaretPosition( displayArea.getText().length() );
}
//processa problemas ocorridos no criação ou no evento do pacote
catch ( IOException ioException )
{
displayArea.append( ioException.toString() + "\n" );
ioException.printStackTrace();
}
}//fim do método actionPerformed
}//fim da classe interna anônima

);//fim da chamada addActionListener

container.add( enterField, BorderLayout.NORTH );

displayArea = new JTextArea();
container.add( new JScrollPane( displayArea ), BorderLayout.CENTER );
setSize( 400, 300 );
setVisible( true );

//cria DatagramSocket para enviar e receber pacotes
try
{
socket = new DatagramSocket();
}
//captura problemas ocorridos na criação do DAtagramSocket
catch( SocketException socketException )
{
socketException.printStackTrace();
System.exit( 1 );
}
}//fim do construtor Client_D

//espera que os pacotes cheguem do Servidor,
//depois exibe o conteudo dos pacotes
public void waitForPackets()
{
//repete o laço para sempre
while( true )
{
//recebe o pacote e exibe o conteudo
try
{
//configura o pacote
byte data[] = new byte[ 100 ];
receivePacket = new DatagramPacket( data, data.length );

//espera o pacote
socket.receive( receivePacket );

//exibe o conteudo do pacote
displayPacket();
}
//processa problemas ocorridos no recepção ou exibição do pacote
catch( IOException exception )
{
displayArea.append( exception.toString() + "\n" );
exception.printStackTrace();
}
}//fim do while
}//fim do método waitForPackets

//exibe conteudo do receivePacket
private void displayPacket()
{
displayArea.append( "\nPacote Recebido:" +
"\ndo Host: " + receivePacket.getAddress() +
"\nPorta do Host: " + receivePacket.getPort() +
"\nTamanho: " + receivePacket.getLength() +
"\nContendo:\n\t" +
new String( receivePacket.getData(), 0, receivePacket.getLength() )
);
displayArea.setCaretPosition( displayArea.getText().length() );

}

//executa o aplicativo
public static void main(String[] args) {
Client_D application = new Client_D();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
application.waitForPackets();
}
}//fim da classe Client_D

Na imagem a seguir temos ambas aplicações:

Fonte:

Nenhum comentário:

Postar um comentário

Obrigado por Participar do programero, fique a vontade para agradecer, retificar, perguntar ou sugerir.