aplicação cliente/servidor

Estava vendo o seu problema, e eu acho q devo ter alguma coisa na minha casa qd chegar eu vejo se encontro…

EDITADO PELA MODERAÇÃO

Olá HJ

Tomara q vc tenha alguma coisa que possa me ajudar.
Que ta dificil fazer.
Ai quem puder ajudar … agradeço

Obrigada

elisangela.bruno

Fiz algumas alterações no seu projeto:

a) Dividi ele em 2 packages, uma é o client e o outro o server, de modo que a estrutura ficou assim:

nomeDoProjeto\src
\client
\server
\Util

b) Fiz com que as classes ficassem em arquivos separados.

c) Fiz alguns ajustes na interface, nada demais, apenas inclui alguns objetos visuais.

Portanto quando receber esta mensagem vc, por favor, faça o seguinte:

  1. Crie um novo projeto java no eclipse.
  2. Clrie no SRC do projeto 2 packages um chamado CLIENT e o outro SERVER.
  3. Copie as classes correspondente ao client para o package CLIENT.
  4. Copie as classes correspondente ao server para o package SERVER.
  5. Execute o server (classe ChatServer).
  6. Execute o client (classe ClientCall).

Segue abaixo as classes do CLIENT:

[code]package client;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ClientCall extends JFrame {

public static final int DEFAULT_PORT = 4321;
private Socket server;
private Thread reader;
public PrintStream outPut;

// Criação dos objetos da tela
private JLabel lblMiniChat = new JLabel("::.. MiniChat Conexão Socket ..::");
private JLabel lblUsuario = new JLabel("Nome do usuario");
private JButton btnLimpar = new JButton("Limpar");
private JButton btnSair = new JButton("Sair");
private JButton btnLogin = new JButton("Login");
private JButton btnSend = new JButton("Enviar");
private JTextField txtUsuario = new JTextField(15);
private JTextField inputArea  = new JTextField(20);
private JTextArea outputArea = new JTextArea(10, 45);
private JComboBox cbxUsuarios = new JComboBox();

public ClientCall() {
	this.initialize();
	this.connect();
}

private void connect() {
	try {
		// Cria um socket cliente passando o endereco e a porta do servidor
		this.server = new Socket("127.0.0.1", DEFAULT_PORT);
		this.reader = new Reader(this);
		this.outPut = new PrintStream(this.server.getOutputStream());
		this.reader.setPriority(3);
		this.reader.start();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

private void send(String msg) {
	this.outPut.println(msg);
}

public void addLogin(String user) {
	if( !user.equals(this.txtUsuario.getText())) {
		if( !this.userExists(user) ) {
			this.cbxUsuarios.addItem(user);
		}
	}
}

private boolean userExists(String user) {
	boolean exist = false;
	
	for(int i = 0; i < this.cbxUsuarios.getModel().getSize(); i++ ) {
		String u = (String)this.cbxUsuarios.getModel().getElementAt(i);
		if( u.equals(user)) {
			exist = true;
			break;
		}
	}
	
	return exist;
}

public Socket getServer() {
	return this.server;
}

public JTextArea getOutPutArea() {
	return this.outputArea;
}

private void initialize() {
	super.setTitle("::.. Comunicador Instântaneo ..::");
	super.setDefaultCloseOperation(EXIT_ON_CLOSE);

	super.setResizable(false);

	super.setLocationRelativeTo(null);

	Container janela = getContentPane();
	janela.setLayout(new FlowLayout());

	// Formatando Fonte
	this.outputArea.setFont(new Font("Serif", Font.ITALIC, 16));
	this.txtUsuario.setFont(new Font("Serif", Font.ITALIC, 16));
	
	// Adicionado componentes
	janela.add(this.lblMiniChat);
	janela.add(this.lblUsuario);
	janela.add(this.txtUsuario);
	janela.add(this.btnLogin);		
	janela.add(this.outputArea);
	janela.add(new Label("Digite a mensagem"));
	janela.add(this.inputArea);
	janela.add(this.cbxUsuarios);
	janela.add(this.btnSend);
	janela.add(this.btnLimpar);
	janela.add(this.btnSair);
	
	// Dimensões Janela
	super.setSize(550, 350);

	// Ações Botões
	this.btnLimpar.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent e) {
			inputArea.setText("");
		}
		
	});
	
	this.btnLogin.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent e) {
			send("LOGIN:"+txtUsuario.getText());
		}
		
	});
	
	this.btnSend.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent e) {
			StringBuilder sb = new  StringBuilder(0);
			sb.append("FROM:");
			sb.append(txtUsuario.getText());
			sb.append(";");
			sb.append("TO:");
			sb.append((String)cbxUsuarios.getSelectedItem());
			sb.append(";");
			sb.append("MSG:");
			sb.append(inputArea.getText());
			send(sb.toString());
		}
		
	});
	
	this.btnSair.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent e) {
			System.exit(0);
		}
		
	});
}

public static void main(String[] args) {
	ClientCall tc = new ClientCall();
	tc.setVisible(true);
}

}
[/code]

[code]package client;

import java.io.DataInputStream;
import java.io.IOException;

import util.Util;

//----------------------------------------------------------------------------
//A classe Reader le a entrada do soquete e atualiza a OutputArea com as
//novas mensagens.
class Reader extends Thread {
protected ClientCall client;

public Reader(ClientCall client) {
	super("chatclient Reader");
	this.client = client;
}

public void run() {
	DataInputStream in = null;
	String line;
	try {
		in = new DataInputStream(client.getServer().getInputStream());
		while (true) {
			line = in.readLine();

			String login = Util.getContent("LOGIN", line);

			if (login != null && login.length() != 0) {
				this.client.addLogin(login);
			} else {
				this.client.getOutPutArea().append(line+"\n");
			}
		}
	} catch (IOException e) {
		System.out.println("Reader:" + e);
	}
}

}
[/code]

Segue abaixo as classes do package SERVER:

package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Calendar;
import java.util.Vector;

public class ChatServer extends Thread
{
  int DEFAULT_PORT=4321;
  protected int port;
  protected ServerSocket server_port;
  protected ThreadGroup CurrentConnections;
  protected Vector connections;
  protected ServerWriter writer;
  private Calendar datatual;

  //Criar um ServerSocket
  public ChatServer()
  {
    super("Server");
    this.port=DEFAULT_PORT;
    try
    {
      server_port=new ServerSocket(port);
    }
    catch (IOException e)
    {
      System.err.println(e+"Exception");
    }
    //Cria um threadgroup para as conexoes
    CurrentConnections=new ThreadGroup("Server Connections");

    //Mensagem inicial na janela do servidor
    System.out.println("::.. Conexoes Realizadas ..::");

    //Um vetor para armazenar as conexoes
    connections=new Vector();
    writer=new ServerWriter(this);

    //Inicia o servidor para ouvindo as conexoes
    this.start();
  }

  public void run()
  {
    try
    {
      while(true)
      {
        datatual = Calendar.getInstance();
        Socket cliente_socket=server_port.accept();
        //Exibe na janela do servidor os clientes que conectam (mostra o host
        //do cliente, a porta e a data e hora da conexao 
        System.out.println("Host:"+cliente_socket.getInetAddress()+"³ Porta:"+
                            cliente_socket.getPort()+"³ "+datatual.getTime());
        Connection c=new Connection(cliente_socket,CurrentConnections,3,writer);
        //evita o acesso simultaneo
        synchronized(connections)
        {
          //adiciona esta nova conexao a lista
          connections.addElement(c);
        }
      }
    }
    catch(IOException e)
    {
      System.err.println(e+"Exception");
    }
  }

  //Inicia o servidor
  public static void main(String[] args)
  {
    new ChatServer();
  }
}
//----------------------------------------------------------------------------
package server;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

import util.Util;

class Connection extends Thread {
	static int numberOfConnections = 0;
	protected Socket client;
	protected DataInputStream in;
	protected PrintStream out;
	protected ServerWriter writer;
	private String user = "";

	public Connection(Socket cliente_socket, ThreadGroup CurrentConnections, int priority, ServerWriter writer) {
		
		super(CurrentConnections, "Connection number" + numberOfConnections++);
		
		this.setPriority(priority);
		
		client = cliente_socket;
		
		this.writer = writer;
		
		try {
			// Atarraxa os streams aos streams de entrada e saida do socket do
			// cliente e adiciona este outputstream ao vetor que contem todos
			// os streams de saida, usados pelo escritor writer
			in = new DataInputStream(client.getInputStream());
			out = new PrintStream(client.getOutputStream());
			writer.outputStreams.addElement(out);
		} catch (IOException e) {
			try {
				client.close();
			} catch (IOException e2) {
				System.err.println("Exception while getting socket streams:" + e);
				return;
			}
		}
		// dispara Thread
		this.start();
	}
	
	public String getUser() {
		return this.user;
	}

	// O metodo run faz um laco lendo as mensagens recebidas
	public void run() {
		String inline;
		// Envia uma mensagem de boas vindas ao cliente
		out.println("Bem vindo ao Comunicador Instântaneo...");
		try {
			while (true) {
				// le uma linha de mensagem
				inline = in.readLine();
				// A conexao eh interrompida se null
				if (inline == null) {
					break;
				}
				
				String u = Util.getContent("LOGIN", inline);
				
				if( u != null && u.length() != 0) {
					this.user = u;
				}
				
				// Joga a linha no escritor writer
				writer.setOutdata(inline);
				synchronized (writer) {
					// chama o escritor synchronized() para evitar que duas
					// linhas
					// Connection o chamem ao mesmo tempo. Esta e uma forma de
					// "bloqueio".
					writer.notify();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				client.close();
			} catch (IOException e2) {
				e2.printStackTrace();
			}
		}
	}
}
package server;

import java.io.PrintStream;
import java.util.Vector;

import util.Util;

class ServerWriter extends Thread {
	protected ChatServer server;
	public Vector outputStreams;
	public String outdata;
	private String outputline;

	public ServerWriter(ChatServer s) {
		super(s.CurrentConnections, "Server Writer");
		server = s;
		outputStreams = new Vector();
		this.start();
	}

	public void setOutdata(String mensagem) {
		outdata = mensagem;
	}

	public synchronized void run() {
		while (true) {
			// A linha faz um laco para sempre, mas na vedade so e executada
			// quando
			// a condicao wait for reinicializada por um notify. Isso num bloco
			// sincronizado para bloquear a linha e evitar o acesso multiplo.
			try {
				this.wait();
			} catch (InterruptedException e) {
				System.out.println("Caught an Interrupted Exception");
			}
			outputline = outdata;

			String login = Util.getContent("LOGIN", outputline);
			String from = Util.getContent("FROM", outputline);
			String to = Util.getContent("TO", outputline);
			String msg = Util.getContent("MSG", outputline);

			synchronized (server.connections) {

				if (login != null) {
					for (int index = 0; index < outputStreams.size(); index++) {
						// Eh impressa a mensagem em cada um OutputStreams.
						PrintStream out = (PrintStream) outputStreams.elementAt(index);

						for (int idx = 0; idx < server.connections.size(); idx++) {
							Connection c = (Connection) server.connections.elementAt(idx);
							out.println("LOGIN:" + c.getUser());
						}
					}
				} else {
					for (int i = 0; i < server.connections.size(); i++) {
						Connection c = (Connection) server.connections.elementAt(i);

						if (c != null && c.getUser().equals(to)) {
							PrintStream out = (PrintStream) outputStreams.elementAt(i);
							out.println(from+" DIZ "+msg);
						}
					}
				}
			}
		}
	}
}

Segue abaixo a classe correspondente ao package UTIL:

package util;

public final class Util {
	public static String getContent(String tag, String msg) {
		String result = null;
		
		String[] parts = msg.split(";");
		
		for( String p : parts) {
			String[] tags = p.split(":");
			
			if(tags[0].equals(tag)) {
				result = tags[1];
				break;
			}
		}
		
		return result;
	}
}

flws

Constroi o projeto e faz alguns testes para ver se está funcionando pra você.

Fiz um pouco as pressas e não tive tempo de fazer um revisão.

Tentei não alterar demais o código, para não atrapalhar seu entendimento.

Espero te-la (caso vc não seja um FAKE) deixado “na cara do gol” com essas alterações.

flws

Fantomas

To fazendo as alterações para testar

Assim q terminar lhe aviso

Mas desde já agradeço a ajuda

Fantomas

era isso mesmo que precisava obrigada

tem alguns erros mas conserto

Valeu mesmo vc não imagina o quanto.

:smiley:

:smiley:

Agora vou começar a fazer um em outra linguagem q depois tenho q interagir duas linguagem …
Acho q ai vem a pior parte

Fontamas

Mais uma coisa sobre o envio das mensagens.
Quando envio as mensagens não fica na tela de quem mandou somente para o destino.
Gostaria de saber se existe a possibilidade de colocar para a origem tb as msg, ou ela pode sobrescrever ou perder os dados.

Aguardo

obrigada

Oi Elisangela,

Se entendi bem o que vc pediu, segue abaixo o código alterado.

Procure as linhas com “<–<<”, são 2 linhas, uma foi incluida e outra alterada.

package server;

import java.io.PrintStream;
import java.util.Vector;

import util.Util;

class ServerWriter extends Thread {
	protected ChatServer server;
	public Vector outputStreams;
	public String outdata;
	private String outputline;

	public ServerWriter(ChatServer s) {
		super(s.CurrentConnections, "Server Writer");
		server = s;
		outputStreams = new Vector();
		this.start();
	}

	public void setOutdata(String mensagem) {
		outdata = mensagem;
	}

	public synchronized void run() {
		while (true) {
			// A linha faz um laco para sempre, mas na vedade so e executada
			// quando
			// a condicao wait for reinicializada por um notify. Isso num bloco
			// sincronizado para bloquear a linha e evitar o acesso multiplo.
			try {
				this.wait();
			} catch (InterruptedException e) {
				System.out.println("Caught an Interrupted Exception");
			}
			outputline = outdata;

			String login = Util.getContent("LOGIN", outputline);
			String from = Util.getContent("FROM", outputline);
			String to = Util.getContent("TO", outputline);
			String msg = Util.getContent("MSG", outputline);

			synchronized (server.connections) {

				if (login != null) {
					for (int index = 0; index < outputStreams.size(); index++) {
						// Eh impressa a mensagem em cada um OutputStreams.
						PrintStream out = (PrintStream) outputStreams.elementAt(index);

						for (int idx = 0; idx < server.connections.size(); idx++) {
							Connection c = (Connection) server.connections.elementAt(idx);
							out.println("LOGIN:" + c.getUser());
						}
					}
				} else {
					for (int i = 0; i < server.connections.size(); i++) {
						Connection c = (Connection) server.connections.elementAt(i);

						String usuario = c.getUser(); // <--<< INCLUI ESTA LINHA
						
						if (c != null && (usuario.equals(to) || usuario.equals(from))) { // <--<< ALTEREI ESTA 
							PrintStream out = (PrintStream) outputStreams.elementAt(i);
							out.println(from+" DIZ "+msg);
						}
					}
				}
			}
		}
	}
}

flws

fantomas

E isso mesmo, mas ele ta conseguindo manda só uma mensagem as proximas estão dando erro.

No meu projeto está executando normalmente.

Que erro esta ocorrendo?

flws

Consegui fazer funcionar.

Obrigada

:smiley:

Vou preparar um explicação do código, para enviar; infelizmente o código que esta sendo utilizado, apesar de funcionar, ele não é muito didatico vamos dizer assim.

flws

E bem isso mesmo

Disse tudo na sua explicação.

Vou aguardar .
Obrigada

Oia eu aqui de novo,

Para entender o código vc dever ficar atenta (se vc não for uma FAKE) a dois detalhes bastante importantes:

OBS. Obser as setas indicativas que coloquei no código.

a) Este código que fica na classe ChatServer.

        synchronized(connections)
        {
          //adiciona esta nova conexao a lista
          connections.addElement(c);    // <-------------------<< LINHA IMPORTANTE
        }

Toda vez que alguem se conecta (login) é incluido um objeto do tipo Connection em uma
lista ( connections )

b) Este código que fica na classe Connection.

		try {
			in = new DataInputStream(client.getInputStream());
			out = new PrintStream(client.getOutputStream());
			writer.outputStreams.addElement(out); // <-------------------<< LINHA IMPORTANTE
		} catch (IOException e) {
			try {
				client.close();
			} catch (IOException e2) {
				System.err.println("Exception while getting socket streams:" + e);
				return;
			}
		}

Toda vez que um objeto do tipo Connection é criado o stream do socket que conecta o servidor ao cliente é incluido
em uma lista que está na classe ServerWriter.

Agora vamos falar do trafico das mensagens que ocorre na classe ServerWriter:

a) Toda mensagem que chega ela tem umas especies de “tags”, foi construida uma classe utilitaria
que informa qual o conteúdo correspondente a tal “tag”. A tag “FROM” por exemplo diz quem enviou
a mensagem.

			String login = Util.getContent("LOGIN", outputline);
			String from = Util.getContent("FROM", outputline);
			String to = Util.getContent("TO", outputline);
			String msg = Util.getContent("MSG", outputline);

b) Se a tag login NÃO estiver vazia, quer dizer que alguem está efetuando uma operação de login,
logo a lista de streams e a lista de conexões são percorridas para que o ComboBox do Client
seja atualizado com o novo usuário. Aqueles que já estão conectados também são atualizados com
o usuário que acaba de ser incluido.

				if (login != null) {
					for (int index = 0; index < outputStreams.size(); index++) {
						// Eh impressa a mensagem em cada um OutputStreams.
						PrintStream out = (PrintStream) outputStreams.elementAt(index); // <---<< Obtem o stream da lista.

						for (int idx = 0; idx < server.connections.size(); idx++) {
							Connection c = (Connection) server.connections.elementAt(idx); // <--<< Atualiza o stream do client com o usuário da conexão.
							out.println("LOGIN:" + c.getUser()); // <---<< INFORMA AOS CLIENTs QUE É UM LOGIN
						}
					}
				}

c) Quando o que chega no servidor não é um LOGIN, a lista de conexões é percorrida na intenção de localizar o usuário
destino da mensagem. Quando o usuário é encontrado, o stream correspondente é adquirido (outputStreams.elementAt(i)) e
utilizado para enviar a mensagem que acaba de chegar. Na versão inicial a lista de streams era percorrida e a mensagem
era enviada para todos os streams contidos na lista, ou seja, todos os usuários recebiam a mensagem.

					for (int i = 0; i < server.connections.size(); i++) {
						Connection c = (Connection) server.connections.elementAt(i); // <----<< Linha importante

						String usuario = c.getUser(); 
						
						if (c != null && (usuario.equals(to) || usuario.equals(from))) {  // <----<< Linha importante
							PrintStream out = (PrintStream) outputStreams.elementAt(i); // <----<< Linha importante
							out.println(from+" DIZ "+msg);
						}
					}

Espero ter aumentado seu entendimento a respeito do código.

Aquele Java abraço pra você.

Fantomas

Agora deu para clarear bastante hehe

Q não sou uma experiente nisso hehe

Mas valeu pela grande ajuda.

:lol:
:wink:
Um Grande java abraço para vc tb