Apostila de Programaç ão Distribuída Introduç ão Parte desse material é fortemente baseado no livro Java: Como programar de Deitel e Deitel e utiliza os mesmos exemplos do livro supra citado. Implementando um servidor simples utilizando Sockets Nesta seção nós trataremos da implementação de um servidor que trata as conexões e se comunica com possíveis softwares clientes. Basicamente tal implementação que utiliza sockets requer cinco passos funcionar corretamente. Passo 1: Criar um objeto do tipo ServerSocket: ServerSocket server = new ServerSocket ( porta, limite ); onde a variável porta especifica a porta na qual o serviço estará disponível, e limite determina a quantidade de clientes que podem aguardar o estabelecimento de uma conexão. Passo 2: O programa deve gerenciar as requisições dos clientes, para tanto deve ser criado um objeto do tipo Socket para cada requisição aceita pelo objeto ServerSocket: Socket connection = server.accept(); Passo 3: após o estabelecimento do servidor e da conexão é necessário que a comunicação entre os softwares seja possível. Para tanto, um objeto do tipo OutputStream e um objeto do tipo InputStream devem ser usados para enviar e receber bytes, respectivamente. ObjectInputStream input = new ObjectInputStream ( connection.getInputStream() ); ObjectOutputStream output = new ObjectOutputStream ( connection.getOutputStream() ); Passo 4: este passo diz repeito a comunicação propriamente dita entre as partes, ou seja, a troca de bytes através da rede entre cliente e servidor. É necessário utilizar os métodos writeObject(object) e readObject() dos objetos do tipo OutputStream e InputStream, respectivamente. String message = “Conexão Estabelecida”; output.writeObject ( message ); output.flush(); String message = (String) input.readObject (); é importante lembrar que existem vários métodos que possibilitam a leitura e escrita a partir de streams, no exemplo acima os métodos usados são de escrita e leitura de objetos, no caso, especificamente, são enviadas e recebidas Strings. Entretanto é possível enviar e receber vários outros objetos, arquivos, etc. Passo 5: por último caso a comunicação não seja mais necessária as streams são finalizadas e a conexão encerrada. output.close(); input.close(); connection.close(); A seguir é apresentado o código fonte em Java de um servidor simples para troca de menssagens: package clientserver; import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Server extends JFrame { private JTextField enterField = new JTextField(); private JTextArea displayField = new JTextArea(); private ObjectOutputStream output; private ObjectInputStream input; private ServerSocket server; private Socket connection; private int counter = 0; public Server() { Container container = getContentPane(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); enterField.setEnabled(false); // adiciona o evento que chama sendData, o qual envia mensagens // ao cliente enterField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { sendData(e.getActionCommand()); } }); container.add(enterField,BorderLayout.NORTH); container.add(new JScrollPane(displayField),BorderLayout.CENTER); setTitle("Server"); setSize(300,150); setVisible(true); } // estabelece e roda o servidor public void runServer() { try { // Passo 1: server = new ServerSocket(5000,100); while(true) { //Passo 2: waitForConnection(); //Passo 3: getStreams(); //Passo 4: proccessConnection(); //Passo 5: closeConnection(); counter++; } } catch(Exception except) { except.printStackTrace(); } } protected void waitForConnection() throws IOException { displayField.append("Aguardando requisição de conexão ...\n"); connection = server.accept(); displayField.append("Atendendo requisição número: "+counter+ " do endereço: "+connection.getInetAddress().getHostName()); } public void getStreams() throws IOException { output = new ObjectOutputStream( connection.getOutputStream() ); output.flush(); input = new ObjectInputStream( connection.getInputStream() ); displayField.append("\nCanais de E/S prontos ... "); } public void proccessConnection() throws IOException { String message ="SERVER >> Conexão estabelecida com sucesso ..."; output.writeObject(message); output.flush(); enterField.setEnabled(true); do { try { message = (String) input.readObject(); displayField.append("\n" + message); } catch(ClassNotFoundException except) { displayField.append("\n"+except.getMessage()); } } while(!message.equals("CLIENT >> Finalize")); } public void closeConnection() throws IOException { displayField.append("\nConexão encerrada pelo Cliente ..."); output.close(); input.close(); connection.close(); } public void sendData(String message) { try { output.writeObject("SERVER >> "+message); output.flush(); displayField.append("\nSERVER >> "+message); } catch(IOException except) { displayField.append("\n"+except.getMessage()); } } public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getLookAndFeelDefaults()); } catch (Exception ex) { ex.printStackTrace(); } new Server().runServer(); System.exit(0); } } Implementando um cliente simples utilizando Sockets A implementação de um cliente é semelhante ao servidor, entretanto enquanto o servidor espera alguma conexão usando um objeto ServerSocket através do método accept(), o cliente requisita uma conexão usando um objeto Socket o endereço do servidor e a porta de serviço. O restante é semelhante ao servidor, veja abaixo a implementação do cliente: package clientserver; import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Client extends JFrame { private JTextField enterField = new JTextField(); private JTextArea displayField = new JTextArea(); private ObjectOutputStream output; private ObjectInputStream input; private Socket client; private String serverHost; public Client(String host) { Container container = getContentPane(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); enterField.setEnabled(false); // adiciona o evento que chama sendData, o qual envia mensagens // ao servidor enterField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { sendData(e.getActionCommand()); } }); container.add(enterField,BorderLayout.NORTH); container.add(new JScrollPane(displayField),BorderLayout.CENTER); serverHost = host; setTitle("Client"); setSize(300,150); setVisible(true); } // estabelece e roda o cliente public void runClient() { try { // Passo 1: connectToServer(); //Passo 2: getStreams(); //Passo 3: proccessConnection(); //Passo 4: closeConnection(); } catch(Exception except) { except.printStackTrace(); } } protected void connectToServer() throws IOException { displayField.append("Estabelecendo conexão com o servidor ...\n"); client = new Socket(InetAddress.getByName(serverHost),5000); displayField.append("Conectado ao servidor: "+ client.getInetAddress().getHostName()); } public void getStreams() throws IOException { output = new ObjectOutputStream( client.getOutputStream() ); output.flush(); input = new ObjectInputStream( client.getInputStream() ); displayField.append("\nCanais de E/S prontos ... "); } public void proccessConnection() throws IOException { String message ="CLIENT >> Iniciando comunicação ..."; output.writeObject(message); output.flush(); enterField.setEnabled(true); do { try { message = (String) input.readObject(); displayField.append("\n" + message); } catch(ClassNotFoundException except) { displayField.append("\n"+except.getMessage()); } } while(!message.equals("SERVER >> Finalize")); } public void closeConnection() throws IOException { displayField.append("\nConexão encerrada pelo Servidor ..."); output.close(); input.close(); client.close(); } public void sendData(String message) { try { output.writeObject("CLIENT >> "+message); output.flush(); displayField.append("\nCLIENT >> "+message); } catch(IOException except) { displayField.append("\n"+except.getMessage()); } } public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getLookAndFeelDefaults()); } catch (Exception ex) { ex.printStackTrace(); } new Client("localhost").runClient(); System.exit(0); } }