aplicação cliente/servidor

Bom dia

Não tenho muita experiencia em programação
Estou desenvolvendo uma aplicação cliente servidor com socket e gostaria de saber como posso verificar os usuarios que estão conectados para escolher para quem devo mandar as mensagens , já está funcionando como se fosse um chat.

Obrigada

Aguardo

Qualquer coisa posto o codigo para facilitar

Desenvolvi uma aplicação semelhante a pouco tempo.
Havia um método através do qual o cliente efetuava login. Neste momento, o servidor adicionava este cliente a uma lista de clientes ativos. Caso o cliente permanecesse mais do que alguns segundos sem atividade alguma, ele era considerado inativo e retirado desta lista.
Havia também um método através do qual o cliente obtinha uma lista com os usuários ativos.

Assim mesmo que preciso

Teria como você me ajudar fazer isso?

Posso tentar de ajudar.
Qual sua dúvida?
Você já iniciou o projeto?

É isso ai, dê mais detalhes…quem sabe eu também não dou uns “toques”.

flws

então gente

Já consegui fazer o cliente / servidor se comunicarem, mas ele manda mensgem para todos que estão conectados

quer q poste o codigos do cliente e do servidor?

Se vc puder fazer esta gentileza, seria ótimo.

flws

Os codigos são : mas ainda terá algumas modificações, pois peguei como base um q faz por console e coloquei interface grafica

Servidor

[code]package Client;

import java.awt.;
import java.net.
;
import java.io.;
import java.util.
;

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©;
}
}
}
catch(IOException e)
{
System.err.println(e+“Exception”);
}
}

//Inicia o servidor
public static void main(String[] args)
{
new chatserver();
}
}
//----------------------------------------------------------------------------
class Connection extends Thread
{
static int numberOfConnections=0;
protected Socket client;
protected DataInputStream in;
protected PrintStream out;
protected ServerWriter writer;

public Connection(Socket cliente_socket, ThreadGroup CurrentConnections,
int priority, ServerWriter writer)
{
super(CurrentConnections,“Connection number”+numberOfConnections++);
//define a prioridade
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();
}

//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;
//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)
{}
finally
{
try
{
client.close();
}
catch(IOException e2)
{}
}
}
}
//----------------------------------------------------------------------------
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;
synchronized(server.connections)
{
for (int i=0 ; i<OutputStreams.size() ; i++)
{
//Eh impressa a mensagem em cada um OutputStreams.
PrintStream out;
out=(PrintStream)OutputStreams.elementAt(i);
out.println(outputline);
}
}
}
}
}[/code]

Cliente

[code]import java.awt.Button;
import java.awt.Container;
import java.awt.Event;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Label;
import java.awt.ScrollPane;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class ClienteCall extends JFrame implements ActionListener {

public static final int DEFAULT_PORT = 4321;
public Socket clisoc;
private Thread reader;
public PrintStream out;
public String Name;

// Criação dos objetos da tela
private Label lb1;
private Label lb2;
private Button b1;
private Button b2;
private static TextField tf1;
private TextField InputArea;
private TextArea OutputArea;
private ScrollPane sp1;

public ClienteCall() {
	setTitle("::.. Comunicador Instântaneo ..::");
	setDefaultCloseOperation(EXIT_ON_CLOSE);

	setExtendedState(MAXIMIZED_BOTH);
	setResizable(false);

	setLocationRelativeTo(null);
	// Cria as linhas de leitura e escrita e as inicia.

	lb1 = new Label("::.. MiniChat Conexão Socket ..::");
	lb2 = new Label("Nome do usuario");
	b1 = new Button("Limpar");
	b2 = new Button("Sair");
	OutputArea = new TextArea(10, 45);
	InputArea = new TextField(20);
	tf1 = new TextField(15);
	// sp1 = new JScrollPane(OutputArea);

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

	// Formatando Fonte
	OutputArea.setFont(new Font("Serif", Font.ITALIC, 16));
	tf1.setFont(new Font("Serif", Font.ITALIC, 16));

	// Adicionando scrollPane - barra de rolagem automatica
	// sp1
	// .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

	// Adicionado componentes
	janela.add(lb1);
	janela.add(lb2);
	janela.add(tf1);
	janela.add(OutputArea);
	janela.add(new Label("Digite a mensagem e pressione ENTER"));
	janela.add(InputArea);
	janela.add(b1);
	janela.add(b2);

	// Dimensões Janela
	setSize(550, 350);

	// Ações Botões
	b1.addActionListener(this);
	b2.addActionListener(this);

	try {
		// Cria um socket cliente passando o endereco e a porta do servidor
		clisoc = new Socket("127.0.0.1", DEFAULT_PORT);
		reader = new Reader(this, OutputArea);
		out = new PrintStream(clisoc.getOutputStream());
		// Define prioridades desiguais para que o console seja
		// compartilhado
		// de forma efetiva.
		reader.setPriority(3);
		reader.start();
	} catch (IOException e) {
		System.err.println(e);
	}
}


public boolean handleEvent(Event evt) {
	if (evt.target == InputArea) {
		char c = (char) evt.key;

		if (c == '\n')
		// Vigia se o usuario pressiona a tecla ENTER.
		// Isso permite saber a mensagem esta pronta para ser enviada!
		{
			String InLine = InputArea.getText();

			Name = tf1.getText();

			out.println(Name + ":" + InLine);

			InputArea.setText("");

			// Envia a mensagem, mas adiciona o nome do usuario a ela para
			// que os
			// outros clientes saibam quem a enviou.
			return true;
		}
	}
	return false;
}
 

public void actionPerformed(ActionEvent e) {

	if (e.getSource() == b1) {
		InputArea.setText("");

	}
	if (e.getSource() == b2) {
		System.exit(0);

	}
}

public static void main(String[] args) {
	ClienteCall tc = new ClienteCall();
	tc.show();
	

}

}

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

public Reader(ClienteCall c, TextArea OutputArea) {
	super("chatclient Reader");
	this.cliente = c;
	this.OutputArea = OutputArea;
}

public void run() {
	DataInputStream in = null;
	String line;
	try {
		in = new DataInputStream(cliente.clisoc.getInputStream());
		while (true) {
			line = in.readLine();
			// Adiciona a nova mensagem a OutputArea
			OutputArea.appendText(line + "\r\n");
		}
	} catch (IOException e) {
		System.out.println("Reader:" + e);
	}
}

}
[/code]

Estou dando uma olhadinha.

Pergunta: o esquema de teclar ENTER quando a mensagem é digitada está funcionando pra vc?

flws

ESta sim normal

Oia eu aqui denovo.

Eu acho que a saida não será tão simples assim, a não ser que alguem tenha uma idéia melhor.

Vamos falar da situação atual:

  1. Vc tem um servidor socket que faz o seguinte:
    a)Toda vêz que um client se conecta ele cria um objeto que representa a “conexão” do client que acaba de se conectar; para constatar isso veja a classe Connection.
    b)Após a criação da conexão (Connection) ela é adicionada em uma lista que está montada da classe ChatServer; para constatr isso veja o código a seguir que está nesta classe.

synchronized(connections) { //adiciona esta nova conexao a lista connections.addElement(c); }
c)Toda vêz que uma mensagem é enviada por um client, o servidor percorre todas as conexões (ver item anterior) e envia a mensagem para cada cliente contido nesta lista; para verificar isto veja a classe ServerWriter no trecho de código a seguir:

outputline = outdata; synchronized (server.connections) { for (int i = 0; i < OutputStreams.size(); i++) { // Eh impressa a mensagem em cada um OutputStreams. PrintStream out; out = (PrintStream) OutputStreams.elementAt(i); out.println(outputline); } }

SUGESTÃO

a) Hoje a interface se conecta automaticamente, vc teria que fazer a interface (client) se conectar APÓS o usuário informar o NOME dele.

b) Quando o server receber a conexão vc tem que atribuir o nome do usuario ao objeto que representa a conexão (classe Connection).

c) Hoje a interface não permite que vc selecione o usuário que destino da mensagem, vc teria que ajustar isto com um ComboBox, Lista ou mesmo digitando.

d) A interface não tem uma lista dos usuários que já estão conectados, vc teria que incluir esta lista (para facilitar deveria ser a mesma lista mencionada no item anterior).

e) Para montar a lista de usuarios conectados (item c, d) você poderia utilizar o mesmo esquema que é utilizado pelo servidor para enviar as mensagens, ou seja, percorre a lista de conexões e envia o nome do maluco que acabou de se conectar.

f) Hoje após o envio da mensagem o servidor percorre a lista de conexões e envia a mensagem para todos os usuários, você teria que obter o usuário destino contido na mensagem e procura-lo na lista de conexões (ver item b) para enviar a mensagem ao usuario destino correto.

Espero ter ajudado e que vc não tenha deixado este trabalho para a ULTIMA HORA rsrsrsrsr.

flws

Oia eu aqui denovo.

Eu acho que a saida não será tão simples assim, a não ser que alguem tenha uma idéia melhor.

Vamos falar da situação atual:

  1. Vc tem um servidor socket que faz o seguinte:

a) Toda vêz que um client se conecta ele cria um objeto que representa a “conexão” do client que acaba de se conectar; para constatar isso veja a classe Connection.

b) Após a criação da conexão (Connection) ela é adicionada em uma lista que está montada da classe ChatServer; para constatr isso veja o código a seguir que está nesta classe.

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

c) Toda vêz que uma mensagem é enviada por um client, o servidor percorre todas as conexões (ver item anterior) e envia a mensagem para cada cliente contido nesta lista; para verificar isto veja a classe ServerWriter no trecho de código a seguir:

outputline = outdata; synchronized (server.connections) { for (int i = 0; i < OutputStreams.size(); i++) { // Eh impressa a mensagem em cada um OutputStreams. PrintStream out; out = (PrintStream) OutputStreams.elementAt(i); out.println(outputline); } }

SUGESTÃO

a) Hoje a interface se conecta automaticamente, vc teria que fazer a interface (client) se conectar APÓS o usuário informar o NOME dele.

b) Quando o server receber a conexão vc tem que atribuir o nome do usuario ao objeto que representa a conexão (classe Connection).

c) Hoje a interface não permite que vc selecione o usuário que destino da mensagem, vc teria que ajustar isto com um ComboBox, Lista ou mesmo digitando.

d) A interface não tem uma lista dos usuários que já estão conectados, vc teria que incluir esta lista (para facilitar deveria ser a mesma lista mencionada no item anterior).

e) Para montar a lista de usuarios conectados (item c, d) você poderia utilizar o mesmo esquema que é utilizado pelo servidor para enviar as mensagens, ou seja, percorre a lista de conexões e envia o nome do maluco que acabou de se conectar.

f) Hoje após o envio da mensagem o servidor percorre a lista de conexões e envia a mensagem para todos os usuários, você teria que obter o usuário destino contido na mensagem e procura-lo na lista de conexões (ver item b) para enviar a mensagem ao usuario destino correto.

Espero ter ajudado e que vc não tenha deixado este trabalho para a ULTIMA HORA rsrsrsrsr.

flws

Desculpe a mensagem repetida, é que o site informou um erro no envio. :oops:

flws

Olá
Nossa quantas modificações
Mas não deixei para fazer de ultima hora
Teria como me ajudar nestas mudanças?

fantomas, implementei um chat nas aulas de java na faculdade uma vez e funcionava de um modo muito semelhante ao descrito acima.
O servidor tinha uma lista de conexões de clientes com os respectivos nomes, toda mensagem recebida era interpretada de quem ela vinha e enviada pros outros ou pra algum outro específico (o protocolo tinha tokens que indicavam se a msg era broadcast ou pra algum destinatário específico).
Sempre que alguém se conectava enviava o nome de usuário junto ao corpo de mensagem de conexão, o servidor registrava esse nome junto ao socket do cliente e enviava pra lista de todos os usuários a nova lista de nomes de usuários conectados.
Quando alguém era considerado inativo a thread de conexão dele (afinal, há uma thread pra cada conexão nova com listeners do socket) era retirada da lista de conexões e atualizava a lista de usuários pra todo mundo de novo.

Não deu tempo de implementar tudo do jeito que queria, ainda tava naquela de deixar pra última madrugada pré-entrega do projeto =Z prática hoje altamente não recomendada por mim (experiência própria).

Abraços.

Tchello
Teria como me ajudar fazer estas modificações ou dar alguns exemplos como posso fazer que não tenho muito noção.

Então, agora estou no trabalho mas assim que chegar em casa e tiver um tempo (lê-se la pras 20 hrs) posto aqui um pacote que fiz na época pra conexões TCP/IP via socket que já administrava todas as threads bonitinhas, sem que fosse necessário se preocupar com isso.
Embora haja mais o que se fazer.
Acredite, não é difícil fazer isso, é quebrando a cabeça que se vai conseguindo essas coisas.
Lembro-me bem dessa época, o quanto quebrei a cabeça pra entender como o diacho do socket funcionava (só desisti do datagram socket(udp) pq nao tive mais tempo e ateh hoje nao consegui fazer aquela bagaça rodar heheh).
Mas é questão de ter persistência e meter a cara sem medo de ser feliz. Acredite, funciona.

Abraços.

Sem problema Aguardo vc dar uma olhada .
Mas to quebrando tanto a cabeça q ta dificil , pois não tenho muita experiencia.
Mas se puder ajudar vou agradecer muito

Vc está utilizando qual IDE para implementar seus códigos?

Eclipse, NetBeans ou o que?

flws

Eclipse