Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Good

Enviar para todos usuários conectados

Recommended Posts

Estou desenvolvendo um sistema de chat em js+java, conexão via web socket.

 

Quando um usuário se conecta, é gravado a id do usuário num array.

 

Acesse o código aqui, pois aqui no imasters ficou tudo bugado: http://pastebin.com/Rbvmw6VV

Como puderam ver, a função armazena guarda a id do novo usuário.

Então, quando armazenado o servidor vai enviar para o cliente alguns dados pela função send do websocket. A função enviarParaTodos está funcionando normalmente, mas preciso fazer uma função que envie para todos os usuários exceto eu.

 

Não sei como fazer :S

E comecei Java a pouco tempo :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Primeiro, você não precisa fazer isso:

public boolean armazena(String newId) {
    for (int i = 0; i < LISTA_DE_NOMES.size(); i++) {
        if (LISTA_DE_NOMES.get(i).equals(newId))
            return false;
    }
    LISTA_DE_NOMES.add(newId);
    return true;
}

Utilize uma implementação da interface java.util.Set . Implementações de Set não aceitam repetições.

 

Quanto a repetição, bastaria que você tivesse gravado o seu usuário numa variável. E no momento de enviar as mensagens não enviar mensagem para usuário com id igual ao seu.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vergil, como você pode ver.. Naquela função que envia para todos, aquele for tem um tal de Websocket c. Ele não dá para fazer um condicional.

 

E para enviar usando aquela lista de usuários conectados, eu teria que chamar a conexão deste tal usuário.. O qual não da certo.. :S

 

Af isso não tem como editar o post depois de um tempo e nem pode juntar os 2 posts quando o post for meu, então ninguém reclama de flood nem nada..

 

 

 

------------------------------

 

 

As conexões ficam salvadas numa lib do Websocket. A lista de ids de usuários conectados ficam na LISTA_DE_NOMES. Como você pode ver, tem um LISTA_DE_NOMES.add(newId);

Como eu posso inserir a variável de conexão junto com este novo valor do array?

 

Ficando mais ou menos assim:

LISTA_DE_NOMES { 0: (1,var conexao), 1: (451,var conexao)}

 

A função:

    public boolean armazena(int newName, WebSocket conn) {
        for (int i = 0; i < LISTA_DE_NOMES.size(); i++) {
            if (LISTA_DE_NOMES.get(i).equals(newName))
                return false;
        }
        LISTA_DE_NOMES.add(newName);
        return true;
    }

Compartilhar este post


Link para o post
Compartilhar em outros sites

Poderia me dar um exemplo? :S

 

Vou te dar uma ideia. Partamos do ponto em que os ids de usuários são únicos. Dessa forma você resolveria seu problema com um mapa (http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Map.html). Dessa forma você teria uma mapa onde as chaves seriam os ids dos usuários e os valores seriam por exemplo o objeto de conexão.

 

public class MinhaClasse {

  private Map<Integer, WebSocket> conexoes;
  private static Integer meuId = 4521548;

  public MinhaClasse() {
    this.conexoes = new HashMap<Integer, WebSocket>();
  }

  public void armazena(int id, WebSocket conn) {
    this.conexoes.put(id, conn);
  }

  public void enviaParaTodos(String texto) {
    for (WebSocket ws : this.conexoes.values()) {
      ws.send(texto);
    }
  }

  public void enviaParaTodosExecetoAMim(String texto) {
    for (Integer chave : this.conexoes.keySet()) {
      if (chave != meuId) {
        this.conexoes.get(chave).send(texto);
      }
    }
  }
}

No exemplo acima, eu não compilei, talvez tenha algum erro de sintaxe. E também não adicionei nem um import. Fica a ideia.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vergil, o último problema.. Na função armazena:


public boolean armazena(int uid, WebSocket conn) {
boolean jaConectado = false;
for (Integer chave : this.LISTA_DE_NOMES.keySet()) {
if (chave == uid) {
jaConectado = true;
break;
}
}
if(!jaConectado){
this.LISTA_DE_NOMES.put(uid,conn);
}
return true;
}

 

 

quando clico em Run, e que o usuário se conecta fica dando problema na linha do for (linha 154, a linha 57 chama a função armazena):

java.lang.NullPointerException
	at Servidor.armazena(Servidor.java:154)
	at Servidor.onMessage(Servidor.java:57)
	at org.java_websocket.server.WebSocketServer.onWebsocketMessage(WebSocketServer.java:457)
	at org.java_websocket.WebSocketImpl.decodeFrames(WebSocketImpl.java:365)
	at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:154)
	at org.java_websocket.server.WebSocketServer$WebSocketWorker.run(WebSocketServer.java:625)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Realmente eu não entendi o porquê de você ter complicado tanto o código com isso:

public boolean armazena(int uid, WebSocket conn) {
    boolean jaConectado = false;
for (Integer chave : this.LISTA_DE_NOMES.keySet()) {
     if (chave == uid) {
     jaConectado = true;
     break;
     }
}        
 
if(!jaConectado){
           this.LISTA_DE_NOMES.put(uid,conn);
}
        return true;
    }

Tente entender primeiro como funciona o Map. É importante ler a documentação http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Map.html

 

E outra, por padrão, nós só nomeamos objetos em caixa alta quando estes são constantes (final).

 

Agora, pra você ter ajuda quanto ao erro, é de suma importância que você aponte a linha exata que está dando erro. Você disse que está dando erro na linha 154 e agora eu te pergunto: o que tem na linha 154??? Ao que tudo indica, você pode não ter instanciado o mapa de conexões. Confira isso.

Compartilhar este post


Link para o post
Compartilhar em outros sites

AAhh, desculpe.. a linha 154 é:

 

for (Integer chave : this.LISTA_DE_NOMES.keySet()) { 
Entendi, estou vendo que este for para validar se o usuário já está online é desnecessário. Visto que o Map já grava, não aceitando valores repetidos.
Mas como eu posso fazer com que retorne um true ou false, para enviar ao cliente se ele pode se conectar ou não?
Obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Como eu disse, você esqueceu de instanciar o mapa de conexões. No código que te passei antes eu instancio o mapa dentro do construtor da classe.

Mas como eu posso fazer com que retorne um true ou false, para enviar ao cliente se ele pode se conectar ou não?

Do mesmo jeito que você envia mensagem de texto pro usuário.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olha como o código está atualmente:

http://pastebin.com/dUEsXmTX

 

Olhando o código atual, você pode ver que está quase completamnete igual o seu. Eu adicionei um ) throws UnknownHostException { na parte do construtor da classe. Se eu tirar, dá um erro dizendo que precisa colocar.. :S

 

A parte de validar se o usuário está na lista de conexoes eu já sei como fazer... vlw

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pergunta...o motivo do PARA TODOS, também inclui você rsss obvio.

 

Mensagem para TODOS ON, TODOS OFF(inbox), TODOS ADMINISTRADORES, TODOS USUARIOS ?

 

Vc já pensou nisso ?

 

Porque não criar classes ( Administrador,Usuarios,etc...), sendo assim daria para controlar e vc nao precisaria SETAR no codigo exclusivamente para vc.

 

Good Luckk

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não Morpheus... Este sistema de enviar mensagens é apenas para os usuários que estiverem online ao servidor.

 

Um exemplo: eu me conecto ao servidor. O servidor vai retornar alguns dados, mas esses dados não podem ser enviados para mim.

 

Por isso preciso criar a função que envia para todos, exceto eu. E a função que envia todos, em geral!

 

Há diversas informações que não devem ser enviadas para mim. Pois se não daria problema, visualmente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estude o padrão de projetos Observer, ele é fácil de implementar e acho que ajuda a resolver o seu problema.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oww, mas eu tenho noção básica. Não sei fazer quase nada, basicamente só criar funções simples, colocar string, int, boolean, etc..

 

ajudae nesse problema..

 

:S

Compartilhar este post


Link para o post
Compartilhar em outros sites

ajudae nesse problema..

E que problema você está tendo agora?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não conheço a classe WebSocketServer, mas ao que tudo indica o construtor padrão dela tem um throws para a exceção UnknownHostException. O que você tem a fazer é circundar o código do seu construtor com um try/catch ou fazer o que você já fez, passar a exceção pra frente com um throws.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.