Pular para o conteúdo principal

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:

Comentários

Mais visitadas

Iniciar e Parar Serviços do Windows (Delphi)

Em certas ocasiões nos deparamos com a necessidade de manipular determinadas atividades do SO, como iniciar ou parar um banco de dados, ou qualquer outro serviço que esteja funcionando no momento. Segue abaixo um código que encontrei na Internet para tal finalidade (não me recordo à fonte, assim que eu a encontrar colocarei). Iniciar Serviço: uses WinSvc; // // start service // // return TRUE if successful // // sMachine: //   machine name, ie: \SERVER //   empty = local machine // // sService //   service name, ie: Alerter // function ServiceStart(   sMachine,   sService : string ) : boolean; var   //   // service control   // manager handle   schm,   //   // service handle   schs   : SC_Handle;   //   // service status   ss     : TServiceStatus;   //   // te...

Listar arquivos existentes em diretório (Delphi)

Mostraremos uma maneira simples e prática para listar o conteúdo de um diretório com a opção de incluir nessa listagem os arquivos de seus subdiretórios. No exemplo abaixo temos um Edit para receber o diretório a ser pesquisado um CheckBox para indicar se os subdiretórios entrarão na pesquisa um botão para efetuar a pesquisa e um Memo para listar os arquivos encontrados, no final um Edit que receberá o cálculo final (em bytes) da soma do tamanho dos arquivos. procedure TForm1.Button1Click(Sender: TObject); begin   tamanhoTotal := 0;   memLista.Lines.Clear;   ListarArquivos(edtDiretorio.Text, chkSub.Checked);   Edit1.Text := IntToStr( tamanhoTotal ); end; procedure TForm1.ListarArquivos(Diretorio: string; Sub:Boolean); var   F: TSearchRec;   Ret: Integer;   TempNome: string; begin   Ret := FindFirst(Diretorio+'\*.*', faAnyFile, F);   try     while Ret = 0 do ...

Centralizar Texto em Edit

Como todos sabemos o Edit mantém todo texto digitado a esquerda, o que não fica bem quando o usamos para a entrada de números, pois bem, o exemplo abaixo apresenta uma alternativa para centralizar um determinado valor dentro de um Edit: procedure EditChange(Sender: TObject); var vl_label : TLabel; //variável do tipo Label begin vl_label := TLabel.Create(self); //criamos um label WITH vl_label DO BEGIN Font.Name := TEdit(sender).Font.Name; //pegamos a fonte usada no edit Caption := TEdit(sender).Text; //pegamos o conteúdo do edit SendMessage(TEdit(sender).Handle, EM_SETMARGINS, EC_LEFTMARGIN, (TEdit(sender).Width-vl_label.Width) div 2); //centraliza no label e retorna para o edit END ; vl_label.Free; end ;