Dúvida Simples  XML
Índice dos Fóruns » Java Básico
Autor Mensagem
fajohann
Thread.start()
[Avatar]

Membro desde: 07/03/2007 13:49:30
Mensagens: 43
Offline

Boa noite,
Estou implementando um multiserver com sockets e threads e gostaria de saber se é possivel o servidor fazer alguma ação no cliente quando este digitar uma tecla. Por exemplo, se o cliente digitar 'dir' mostrar os diretorios dele ou outra aplicação qualquer.
Desculpe a pergunta mas sou mto iniciante em sockets e já andei pesquisando sobre isso e só acho exemplos mais simples como mostrar a data e hora do servidor e tal mas até agora não vi nada sobre chamar processos internos do cliente dependendo da ação que ele tomar.

Espero que alguém possa me ajudar
Obrigado
[MSN]
douglas_vidotto
JavaTeenager
[Avatar]

Membro desde: 12/08/2008 15:43:18
Mensagens: 195
Offline

Eu sei o básico também de conexões de socket em java. Vou dar uma sugestão, mas pode ser que haja soluções melhores e mais fáceis.

Bom, com o socket você consegue enviar dados do cliente para o servidor e vice-versa, certo? Bom, então, você pode enviar a String que você cria com o comando digitado pelo usuário. No servidor você a recebe e verifica o comando recebido desse cliente. Se for um dir, você pode criar objetos contendo a árvore de diretórios do servidor e enviar para o cliente de volta em um objeto que usa uma Lista ou uma TreeSet, enfim, qualquer coisa.

Não sei se a sugestão é boa, mas pelo pouco conhecimento que tenho, acho que eu faria isso.

Abraços!
Beth_pe
Smalltalk

Membro desde: 30/08/2009 14:15:17
Mensagens: 4
Offline

Alguém pode explicar como a máquina virtual funciona?
fajohann
Thread.start()
[Avatar]

Membro desde: 07/03/2007 13:49:30
Mensagens: 43
Offline

Olá,
Então Douglas, é exatamente isso que eu estou tentando fazer..mas não estou conseguindo enviar o objeto de volta para o cliente...
Por exemplo..para testar se o cliente digitar a string 'shutdown' ou 's' o computador dele deveria desligar...mas não funciona


Não sei como retornar objetos vindos do servidor ou comandos..só strings...
Se vc souber que comando eu uso para devolver objetos ou comandos que não sejam string..agradeço

Valeu

This message was edited 2 times. Last update was at 31/08/2009 13:28:32

[MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20578
Localização: Curitiba/PR
Offline

Já ouviu falar sobre "criar um protocolo"? Se tanto o seu cliente, quanto seu servidor são Java, uma boa também pode ser usar RMI.


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
fajohann
Thread.start()
[Avatar]

Membro desde: 07/03/2007 13:49:30
Mensagens: 43
Offline

Como assim criar um protocolo ?? Sou meio novato nisso...
Mas RMI não posso usar tem que ser usando somente o conceito de sockets

Veja se pode ser implementado assim:

String s - para o cliente digitar determinada palavra o letra;
FileInputStream (ou BufferedInputStream) para ler um arquivo do servidor ou um comando tipo "shutdown" quando o cliente digitar determinada String;
ObjectOutputStream para enviar os Objetos do servidor para o cliente;
ObjectInputStream para ler os Objetos vindos do servidor no cliente;

Seria +/- esse o raciocínio ou não é por ai?

Obrigado
[MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20578
Localização: Curitiba/PR
Offline

O primeiro passo numa aplicação sockets, antes mesmo da programação, é definir como vai ser o protocolo de comunicação entre seu cliente e seu servidor.

O protocolo descreve como as mensagens serão codificadas, que mensagens existirão, etc. Por exemplo, você pode dizer que toda mensagem tem o seguinte formato:

1 int - Tamanho da mensagem
1 byte - Código da mensagem (de 0 até 127)
outros bytes - DADOS DA MENSAGEM

O campo "tamanho da mensagem" é muito importante. É ele que diz ao servidor quantos bytes devem ser lidos, para que aquela mensagem tenha sido completamente recebida. Esteja atento ao detalhe que, em sockets, o número de writes no lado do de quem escreve pode não ter nada a ver com o número de reads necessários no lado de quem lê a mensagem. Por exemplo, é possível que o cliente escreva um grande arquivo com um só write, mas que o servidor precise de vários pequenos reads para ler a mensagem completa, pois os bytes trafegam pela rede devagar e chegam aos poucos. O contrário também pode ocorrer, o cliente pode fazer vários writes pequenos, e os dados chegarem juntos ao servidor, e serem lidos num só read.

Sem a informação do tamanho, é impossível saber quantos bytes esperar, ou até onde ler. E como saber por onde começar a leitura? Nosso protocolo SEMPRE começa com o int de tamanho, ou seja, nosso servidor precisa começar lendo um int, que indica o tamanho da primeira mensagem.

Vamos adiante. A mensagem de código 01, poderia ser a de "listar diretório". Ela, poderia exigir que os outros bytes estivesse preenchidos com uma String, contendo que diretório no servidor seria listado. Vejamos a estrutura da mensagem 01:

String - Caminho a ser listado.

Ela poderia ser respondida pela mensagem 01 do servidor. Essa mensagem, poderia ter o seguinte formato:

Para cada arquivo
1 int - Tamanho da string com o nome do diretório
String - Com o nome do diretório.

Note que como a resposta do servidor serão várias string, precisamos de um byte antes de cada delas para saber, na massa de dados, onde termina uma string e onde outra começa... Outra alternativa seria incluir um caracter separador, como faz o C++. Poderíamos, opcionalmente, fazer assim:

Para cada arquivo (forma opcional)
String - Com o nome do diretório.
um byte contendo o valor 0.

Eu prefiro a primeira forma, pois para os sockets é conveniente saber quantos bytes ler.


Ok, agora que você já sabe como será a conversa do servidor com o cliente, é possível codificar a mensagem que vai para o servidor:


Agora vamos fazer o método de enviar mensagem. Note que no método anterior, eu não incluí o campo do tamanho da mensagem. Isso porque, como esse campo é igual para todas as mensagens, preferi que o método de envio cuidasse desse detalhe. Isso é uma divisão em camadas do protocolo. O método de envio cuida da parte "bruta" que é dizer o tamanho total da massa de dados, e os outros métodos (como o de cima), se preocupam em codificar as mensagens em si.

Alguns protocolos incluem checksums, criptografia, e outras coisas, que poderiam ser colocadas aqui no método de envio. Coisas como essa validam a mensagem, ou a codificam, sem alterar sua estrutura. Como podem ser calculadas externamente, a lógica fica melhor dividida dessa forma.

Como o nosso protocolo é muito simples, e não tem nada disso, vamos ver como o método de envio fica:



Note que para comandar uma listagem de diretório, agora basta fazer:



E como seria a decodificação do servidor? Bom, agora você sabe o que esperar. O primeiro passo é ler quatro bytes (um int), que sabemos (pelo nosso protocolo) que será o tamanho da mensagem.

Depois, lemos a quantidade de bytes indicada nesse parâmetro. O primeiro byte lido, será o código da mensagem. Ao recebermos o código 01, saberemos (pelo protocolo) que, necessariamente, refere-se a uma mensagem de listar diretório.

Os bytes seguintes podem, então, ser seguramente copiados para uma string. E essa string terá o nome do diretório.


Espero que você tenha entendido o conceito. Como o procotolo é seu, sinta-se à vontade de fazer qualquer modificação, inclusive, usar somente strings. As informações estariam contidas nessa string, que deverá ser parseada entre o cliente e o servidor. O seu protocolo definiria então como o parser trabalharia nessa string. Muitos protocolos hoje são feitos dessa forma. É o caso dos protocolos SIP e dos web-services (os últimos usam xml).

Você também pode ler alguma RFC de um protocolo simples, como o TFTP, para ver como os projetistas organizaram o protocolo.

Eu não recomendo que você use somente strings, no entanto. É um bom exercício trabalhar com bytes, e ver como você pode otimizar o protocolo para consumir a menor banda possível. Na verdade, muitos protocolos são orientados a bytes, e seria uma boa experiência você aprender a trabalhar desse jeito também.


Dê uma olhada nesse programa de chat, que já deixei aqui no fórum. Ele aplica esses conceitos:
http://www.guj.com.br/posts/list/15/74218.java#506163

This message was edited 9 times. Last update was at 13/04/2012 11:20:19


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
jidlafe
Debugger
[Avatar]

Membro desde: 10/04/2009 17:09:55
Mensagens: 56
Localização: SBC / SP
Offline

Bem explicado ViniGodoy.

Parabéns.

Que tal aprender Java e ganhar dinheiro.
[Email] [MSN]
fajohann
Thread.start()
[Avatar]

Membro desde: 07/03/2007 13:49:30
Mensagens: 43
Offline

Baa, muito obrigado pela ajuda, vou ver se consigo implementar assim então..
Mas caso o cliente se conectar via Telnet eu também deveria proceder assim ?
Valeu
[MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20578
Localização: Curitiba/PR
Offline

Telnet é o nome do protocolo especificado na RFC854.
http://www.faqs.org/rfcs/rfc854.html

Se você só estiver fazendo um Client, uma boa é usar uma classe já pronta, como essa aqui:
http://commons.apache.org/net/api/org/apache/commons/net/telnet/TelnetClient.html

Cuidado também pq muitas aplicações Telnet podem te enviar codificação Ansii, para texto colorido.
Aí é bom implementar uma espécie de filtro.

This message was edited 1 time. Last update was at 01/09/2009 13:19:31


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
Alanvncs
Smalltalk

Membro desde: 28/04/2012 12:14:38
Mensagens: 3
Offline

Consentimos que é bem melhor que ele crie um protocolo, mas ele não poderia retornar o objeto ao cliente atraves do ObjectOutputStream ?
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20578
Localização: Curitiba/PR
Offline

Alanvncs wrote:Consentimos que é bem melhor que ele crie um protocolo, mas ele não poderia retornar o objeto ao cliente atraves do ObjectOutputStream ?


Eu geralmente acho mais complexo (ou tão complexo quanto). Você tem que garantir diversas coisas:
a) Que todas as classes são serializáveis;
b) Que a serialização é depth e não shallow;
c) Que você trata serializações cíclicas;

Além disso, é pouco prudente não sentar antes e organizar sua comunicação. É muito importante saber que mensagens mandar, quais não mandar e como o servidor garantirá que a conexão ficará viva. Dependendo da carga, o ObjectInputStream também é pouquíssimo eficiente, por serializar dados demais.

Claro, para um sistema simples de faculdade, ele talvez quebre um galho. Mas é justamente na faculdade que você deveria entender os conceitos relacionados a rede, não simplesmente usar frameworks prontos.

This message was edited 1 time. Last update was at 22/05/2012 12:25:07


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
 
Índice dos Fóruns » Java Básico
Ir para:   
Powered by JForum 2.1.8 © JForum Team