Implementando um chat via servlets

24 respostas
Guilherme_Silveira

Depois de uma longe discussao numa lista, decidi copiar aqui tambem o que sei sobre chats, assim quem tiver duvidas do assunto vao saber onde perguntar, se nao solucionar o problema.

Um chat que se mantem no servidor implementado por servlets/jsp costuma possuir dois frames: o TEXTO (onde tem a barra de rolagem) e o FORMULARIO. O protocolo eh sempre HTTP claro.

O formulario pode usar o metodo POST/GET mas o metodo recomendado pode ser o PUT, uma vez que indica enviar algo para alterar uma pagina.

A diferenca cosmetica numa servlet sera qual metodo devera ser implementado, doGet, doPost ou doPut.

A servlet que recebe o formulario ira processar o request e devolver um novo formulario.

Pronto, a segunda parte esta pronta, falta a primeira parte/frame.

Ele eh feito atraves de uma outra/mesma servlet que NAO FECHA A CONEXAO COM O CLIENTE (exemplos: uol, terra). Algumas pessoas pensam que isso ira abusar de conexoes, porem eh a tecnica utilizada por todos os grandes chats. Fora dessa soh existe o metodo de reloads que nem irei comentar.

Desse jeito, essa servlet mantem uma lista com os streams de saida (OutputStream/Writer) e quem eh quem (esses chats sempre fazem aquele opcao de mandar mensagem privada para “Joca Maloca”).
Essa servlet ira dormir ate o usuario clicar STOP no browser (ira jogar uma excecao no codigo: stream fora fechada) ou fechar a janela (idem)… assim voce sabe que o usuario saiu da sala. Claro que voce pode criar um botao SAIR que tambem devera tirar o usuario da sala.

Por ultimo voce precisa fazer com que a cada nova mensagem na servlet que processa FORMULARIOS, essas sejam escritas nos usuarios que estao conectados na servlet de TEXTO (se nao for a mesma).
Para isso voce pode:

  • para cada novo formulario, processar umvetor com uma lista de usuarios conectados e enviar a mensagem para cada Stream deles
  • durante o sleep da servlet de TEXTO, checar se existe algo novo e jogar este novo no stream do usuario.

O primeiro metodo eh muito mais inteligente e rapido, apesar de efetuar uma conexao direta entre duas servlets (nao muito orientado a objeto), mas eh um problema que pode ser solucionado sem muita dor de cabeca.

Bom, eh isso, espero ter solucionado o problema daqueles que nao conseguem imaginar como fazer um chat sem tempos de reload…

Quaisquer duvidas, podem escrever

Guilherme Silveira

24 Respostas

Paulo_Silveira

Tenho uma solucao mais legal ainda!

Cria um objeto estatico que vai ser usado como mutex na servlet

public static Object chat = new Object();

Ai, voce usa o esquema do Guilherme, imprime tudo o que voce ja tem num buffer (static StringBuffer como variavel de classe de servlet, por exemplo), e poe diretao:

while (true) {

  synchronized(chat) {
    chat.wait();
  }

  descarregaRestoDoBuffer();

}

Assim a servlet vai ficar esperando, e várias outras vao ficar esperando. Quando alguem manda uma mensagem, atraves de outra servlet, voce sincroniza atraves dessa variavel CHAT, e da um notifyAll:

ServletDeChat.bufferEstatico.append(mensagem);
synchronized(chat) {
  chat.notifyAll();
}

Todo mundo vai sair do Wait! Ai la voce le o que o cara colocou no buffer, e volta pro wait!

legal neh?

Guilherme_Silveira

essa eh a complicacao q eu falei q nao seria o problema de uma grande dor de cabeca…

mas com certeza ainda acho melhor criar um objeto chamado Cliente ou Usuario com um metodo addMessage() e passa um objeto Message() para ele.
Esse metodo deve entao simplesmente processar essa mensagem.
Eh mais orientado a objeto do que a tua solucioneba meia boca (to brincando)

Gui

Paulo_Silveira

Mas entao no seu caso, as servlets ficam o tempo TODO verificando se tem mensagem nova? Isso eh loucura total! PRECISA de sincronização.

Paulo_Silveira

Digo isto porque voce deu duas solucoes:

Ok, voce envia a mansagem pro stream do cliente. Mas como a thread q ta servindo esse cliente vai descobrir que o stream tem coisa nova? Voce fica dentro de um while(true)?

Esta aqui é muito ruim! De quanto tempo eh o sleep? Se for pouco, vai sobrecarregar o servidor. Se for muito, vai ter lag na conversa!

Guilherme_Silveira

esse segundo q vc falou era o meu primeiro q eu descartei la no texto
o primeiro q vc falou eh o meu segundo no texto q eu adicionei:

que eh exatamente o q vc fez, efetuou a conexao direta enter as duas servlets atraves de um objeto/metodo estatico das duas.
o melhor ainda seria que esse fizesse esse metodo/objeto estatico um pouco mais orientado a objeto e nao soh um simples mutex inutilex

gui

Paulo_Silveira

Mas o seu vetor de OutputStreams (buffers) dos clientes eh estatico.
Nao tem como fugir.

Voce pode fazer um singleton, se qusier disfarcar.

Guilherme_Silveira

o vetor eh estatico mas nao visivel atraves de um getVector()
e sim teria um estatico sendMessageToUser(User,Message);

Gui

Rafael_Steil

Eu tambem quero ter um irmao programador pra mim poder ficar discutindo metodologias de desenvolvimento com ele e outras noias do genero… :mrgreen:

urubatan

da pra fazer isto aqui mesmo com a galera :slight_smile:

perdi o inicio da conversa, mas eu utilizaria a opção mais orientada a objeto mencionada,
com um unico metodo estatico, para adicionar o texto das novas mensagens nos buffers de cada cliente.

ai sincronizaria apenas por este metodo :slight_smile:

aconstantino

Sabendo que deve ser o protocolo HTTP mas ja palpitando… :slight_smile:

No meu ponto de vista a melhor forma é criar um protocolo próprio para o chat (já que o chat em discussão é um chat de grande porte) com encriptação e um servidor distribuindo para os clientes a grande idéia do servidor também é só receber conexões de uma rede local.

Ai então criando o socket poderiamos iniciar o servelet.Uma thread enviando e recebendo dados (isto configurado o timeout do socket ) caso dê timout o usuário é automaticamente desconectado da rede.

Isto por ser bom também para evitar os espertinhos que adoram fazer softwares para conexão em chats do UOL etc…

Guilherme_Silveira

Olha gente, ja terminei o chat que vou usar de exemplo no tutorial, ele nao tem suporte pra salas mas pode ser facilmente adaptado.
Estarei escrevendo agora o tutorial e creio que na sexta terei ele pronto.

Para acessar o chat de exemplo basta incluir teu login no lugar do “SEULOGINAQUI”!

http://www.guj.com.br/servlet/br.guj.chat.ChatServlet?login=SEULOGINAQUI

Abraco

Guilherme

Guilherme_Silveira

nossa
o baguio loto de gente
e ta rapidissimo

J

java.lang.NullPointerException

quando enviei um texto para “todos” no chat

Paulo_Silveira

hehehe
ta dando NullPointer agora mesmo!

Gui, pode apostar que eh cosia do GarbageCollector, ou coisa dos OutputStreams que fecham depois de um tempo!

Rafael_Steil

O Chat nao funciona no meu browser. To usando o galeon 1.2.5 ( q usa como base o mozilla 1.0 ), e ao inves de aparecer os frames, aparece na tela os codigos html … deu pau la no trampo e aki em casa.

Rafael

Paulo_Silveira

ele nao deve ter setado o content type, ou nao ta de acordo com o w3c

esses browsers, tipo lynx e w3m, sao mto chatos

Leonardo

Galera, este chat fará parte do GUJ ?? É uma ótima ideia !

J

Das veiz (sotaque mineiro) acontece de esquecer di inicializar alguma coisa e da esse pau, quem sabe num eh coisa simplis…

Guilherme_Silveira

oi gente
entao, eu mudei um baguio e mandei la e esqueci de testa, meio cabecao neh…
de qq jeito, ta la uma versao q deve rodar
com certeza eu nao setei o content type e nem to muito afim de incluir a linha hoje la nao aehuaeuhaeuhhae… preguica mata
talvez amanha…

gui

J

:smiley: :smiley: :smiley:

Guilherme_Silveira

coloquei suporte a browsers bizarros
espero q funcione

Guilherme_Silveira

versao 0.2 alpha foi lancada
nao tive tempo pra fazer muito do tutorial, soh o comecinho q explica a teoria
tem mais uns 3 4 passos
nao ta dando pq tenh oMUITO TRABALHO pra fazer, sem nocao
de qq jeito o codigo fonte ta aqui:

http://www.guj.com.br/guilherme/chat.zip

Aproveitem e sugestoes sao sempre bem vindas,

Gui

Guilherme_Silveira

o tutorial esta pronto mas ainda nao totalmente acentuado. isso singifica que o paulo ainda deve ter um trabalhinho de uns 2 dias para acentuar e colocar aqui no site. quem puder me dar um feedback eu agradecia

gui

Guilherme_Silveira

novo site pro teste de chat:

http://www.guj.com.br/servlet/br.guj.chat.servlet.Login

quem quiser pode ir testando
adicionei suporte a sala, o que significa que o chat esta na versao 1.0 alpha e soh falta suporte pra um arquivo .txt (properties) que permita configurar o html e as possiveis salas do chat.
essa sera a versao 1.0 beta
ai eh corrigir bug ate morrer e lancar a 1.0

quem estiver disposto a ajudar eu peco pro paulo informacao sobre um cvs q eu possa usar ou caso contrario eu abro um projeto no source forge e preciso de alguem pra fazer o html do site

quem ajuda?

gui

Criado 24 de setembro de 2002
Ultima resposta 11 de out. de 2002
Respostas 24
Participantes 7