terça-feira, 14 de agosto de 2012

RES: RES: [java-br] Socket

·

 

Boa Douglas, brigadão pelas dicas, vamos lá:

Pelo que entendi, então não estou cometendo nenhum grande sacrilégio.

1 - implementar após o accept(), um sistema de login e senha....
R. por enquanto não estou preocupado com a segurança dos dados, somente com
a rapidez e confiabilidade.

2 - separe um pouco as classes, faça o tratamento dos dados assim que
receber a informação, quanto menos Ifs melhor
R. bom eu separei uma que recebe e outra que envia, vc quis dizer tipo não
criar um procedimento e sim fazer direto no IF?

3 - fazer testes de stress, coloque um while(1<1000) na classe (cliente)
para se conectar 1000x e ler/escrever 1000 no socket, depois faça outro
teste, 1000 conexões e 100.000 ler/escrever no socket, de acordo com a dica
abaixo(4)........... veja o tempo que demorou e quanto consumiu de
memoria.....acompanhe o processamento e banda do servidor
R. vou fazer.

4 - quando um cliente realiza conexão é criada uma nova thread para esse
cliente, ai ele envia as informações e desconecta...eu acho que nesse caso é
legal você manter a conexão ativa, segurando uma thread la na classe do
cliente, por exemplo, se conectou...vai enviando informações a vontade, se
alguma tentativa falhar, conecta novamente.
R. Teria como vc me dar um exemplo?

5 - trate as exceções com carinho, de inicio tudo bem você vai dando
exception e descobrindo onde esta os maiores problemas, mais depois com o
tempo, tente tratar as exceções antes delas ocorrerem, para minimizar erros
nos clientes. (que seja com ifs)
R. só ocorre um erro, e no servidor, que é o deadlock, quando dois aparelhos
tentam utilizar o mesmo procedimento. Nos aparelhos não dão boca.

6 - de acordo com a dica acima(5), se pelo que eu entendi, eu tenho um GPS e
falhou vai dar erro e ja era...ai é problema, por que erros vão ter....você
vai ter que ter uma tolerancia a esses erros, por exemplo se eu recebi a
requisição agora: 20s e não recebi a de 40s, você pode ter um Log e
marca-lo, porém sem deixar de funcionar o cliente...
R. quanto a isso tah tranquilo.

O Marcelo me deu um bizu muito legal sobre nios, não blocante, que seria
capaz de receber zilhoes de requisições sem dar pau.

Achei um exemplo assim, enviando a hora do servidor:

Selector acceptSelector = SelectorProvider.provider().openSelector();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
InetAddress lh = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(lh, PORTA_UTILIZADA);
ssc.socket().bind(isa);
SelectionKey acceptKey = ssc.register(acceptSelector,
SelectionKey.OP_ACCEPT);
int keysAdded = 0;

while ((keysAdded = acceptSelector.select()) > 0) {
Set readyKeys = acceptSelector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
SelectionKey sk = (SelectionKey)i.next();
i.remove();
ServerSocketChannel nextReady =
(ServerSocketChannel)sk.channel();
Socket s = nextReady.accept().socket();

//AQUI ELE DEVOLVE A DATA DO SERVIDOR
PrintWriter pw = new PrintWriter(s.getOutputStream(),
true);
Date now = new Date();
pw.println(now);
pw.close();
}
}

Só que neste exemplo ele não separou nada, tá tudo junto e pronto para
receber uma requisição especifica, no caso a hora do servidor, como faria
para dizer neste exemplo o que quero requisitar e o que ele deve me
responder?

[]'s
Luciano

-----Mensagem original-----
De: java-br@yahoogrupos.com.br [mailto:java-br@yahoogrupos.com.br] Em nome
de Douglas Nogueira
Enviada em: terça-feira, 14 de agosto de 2012 13:47
Para: java-br@yahoogrupos.com.br
Assunto: RE: RES: [java-br] Socket

olha, acho que você deve implementar mais coisas ai que são "quase
essenciais": 1 - implementar após o accept(), um sistema de login e
senha.... 2 - separe um pouco as classes, faça o tratamento dos dados assim
que receber a informação, quanto menos Ifs melhor 3 - fazer testes de
stress, coloque um while(1<1000) na classe (cliente) para se conectar 1000x
e ler/escrever 1000 no socket, depois faça outro teste, 1000 conexões e
100.000 ler/escrever no socket, de acordo com a dica abaixo(4)...........
veja o tempo que demorou e quanto consumiu de memoria.....acompanhe o
processamento e banda do servidor 4 - quando um cliente realiza conexão é
criada uma nova thread para esse cliente, ai ele envia as informações e
desconecta...eu acho que nesse caso é legal você manter a conexão ativa,
segurando uma thread la na classe do cliente, por exemplo, se conectou...vai
enviando informações a vontade, se alguma tentativa falhar, conecta
novamente. 5 - trate as exceções com carinho, de inicio tudo bem você vai
dando exception e descobrindo onde esta os maiores problemas, mais depois
com o tempo, tente tratar as exceções antes delas ocorrerem, para minimizar
erros nos clientes. (que seja com ifs) 6 - de acordo com a dica acima(5), se
pelo que eu entendi, eu tenho um GPS e falhou vai dar erro e ja era...ai é
problema, por que erros vão ter....você vai ter que ter uma tolerancia a
esses erros, por exemplo se eu recebi a requisição agora: 20s e não recebi a
de 40s, você pode ter um Log e marca-lo, porém sem deixar de funcionar o
cliente... qualquer dúvida estamos ai To: java-br@yahoogrupos.com.br
From: lvctecno@yahoo.com.br
Date: Tue, 14 Aug 2012 12:13:49 -0300
Subject: RES: [java-br] Socket

Ola Marcelo obrigado pelo interesse na ajuda.

Deixa eu te passar o cenário do problema:

Tenho um aplicativo rodando em Android que se comunica através de HTTP

(paginas jsp) com servidor Tomcat, trabalho com sistemas de rastreamento

cada aparelho me envia de 60 em 60 segundos sua id e localização.

Cada aparelho faz em media 5 requisições por minuto, incluso o envio de

localização, ae tu multiplica isso por 100 aparelhos e vamos chegar na casa

das 500 requisições por minuto, o que as paginas estão dando conta sem

problemas.

O meu problema está no consumo, pois cada requisição hoje, me enviando 0 ou

1 ou nada, consome no aparelho 1Kb, quando percebi que via socket consome

somente 1k, ou seja 1023k a menos.

Consegui depois de muito penar na web, construir um servidor socket assim

(sei que devo estar fazendo altos sacrilégios, mas foi como consegui chegar

e até então meu conhecimento em sockets era abaixo de zero) :

Na classe principal:

public static void main(String[] args) throws IOException {

ServerSocket serverSocket = new ServerSocket(PORTA);

System.out.println("INICIADO");

while(true){

Socket socket = serverSocket.accept();

new ServicoThread(socket).start();

}

}

Na classe Serviço:

public class ServicoThread extends Thread {

private final Socket socket;

public ServicoThread(Socket socket) {

this.socket = socket;

}

@Override public void run() {

try {

DataInputStream in = new

DataInputStream(socket.getInputStream());

DataOutputStream out = new

DataOutputStream(socket.getOutputStream());

ExecutaServico es = new ExecutaServico(in);

es.enviar(out);

out.close();

in.close();

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

Na classe executora assim:

public ExecutaServico(DataInputStream in) {

String nomeServico = "";

try {

this.servico = DataInputStream.readUTF(in).toString().trim();

if(servico.trim().equals("02")){

nomeServico = "LOCALIZACAO";

this.id = DataInputStream.readUTF(in);

this.latitude = DataInputStream.readUTF(in);

this.longitude = DataInputStream.readUTF(in);

this.velocidade = DataInputStream.readUTF(in);

}

public void enviar(DataOutputStream out) throws IOException{

if (this.servico.equals("02")) { //LOCALIZAÇÃO

int i = cadastrarPosicao();

if(i > 0){

out.writeUTF("1");

} else {

out.writeUTF("0");

}

}

public synchronized int cadastrarPosicao(){

int i = 0;

try {

cs = bd.conectar().prepareCall("{call

qry_001(?,?,?,?)}");

cs.setString(1, id);

cs.setString(2, latitude);

cs.setString(3, longitude);

cs.setString(4, velocidade);

i = cs.executeUpdate();

} catch (SQLException ex) {

ex.printStackTrace();

} finally {

try {

if (cs != null){

cs.close();

cs = null;

}

} catch (SQLException c){ }

bd.desconectar();

}

return i;

}

Bom via de regra geral funciona, mas não tenho coragem de colocar em

produção, porque não estou acreditando que este dará conta da quantidade de

requisições, com apenas dois aparelhos em laboratório, a quantidade de

deadlocks é pequena, mas existe, mas com um grande quantidade acredito que

vá explodir.

Se vc puder me ajudar a enquadrar isso que eu fiz até aqui, na maneira como

vc descreveu e conseguirmos montar alguma coisa que responda a uma grande

quantidade de requisições, a gente tenta encarar.

Fique a vontade se quiser me adicionar no MSN.

De antemão muito obrigado pelas informações, cara valeu.

Luciano

De: java-br@yahoogrupos.com.br [mailto:java-br@yahoogrupos.com.br] Em nome

de MarceloMF

Enviada em: terça-feira, 14 de agosto de 2012 11:01

Para: java-br@yahoogrupos.com.br

Assunto: Re: [java-br] Socket

Olá Luciano,

O protocolo http roda em cima do protocolo TCP, você provavelmente devera

escolher entre 2 protocolos:

TCP - Estabelece conexão, realiza o 3way handshake:

PC1 -------------->(SYN) PC2 (Primeiro pacote solicitando conexão)

PC2 ----->(SYN+ACK) PC1 (Segundo pacote confirmando o recebimento do

primeiro)

PC1 -------------->(ACK) PC2 (Terceiro pacote confirmando o recebimento do

segundo e estabelecendo a conexão)

UDP - Não estabelece conexão, não realiza o 3way handshake, por isso é

utilizado para funcionalidades como streeming.

Então é provável que você utilize o TCP, dessa forma você devera criar um

protocolo para trafegar suas informações, normalmente ele se divida em 2

partes:

header -> Informações gerais sobre o pacote/mensagem

payload -> Conteúdo do pacote/mensagem

Exemplo de header:

NOME_TRANSACAO(10POSICOES C/ " " A ESQUERDA)+TAMANHO_PAYLOAD(10POSICOES C/

0 A ESQUERDA)+PAYLOAD(VARIÁVEL)+HASH_PACOTE(64 POSIÇÕES)

Exemplo de payload:

NOME_INFORMACAO1(10POSIÇÕES C/ " " A

ESQUERDA)+TAMANHO_INFORMACAO1(10POSIÇÕES C/ 0 A

ESQUERDA)+INFORMACAO1(VARIÁVEL)

+NOME_INFORMACAO2(10POSIÇÕES C/ " " A

ESQUERDA)+TAMANHO_INFORMACAO2(10POSIÇÕES C/ 0 A

ESQUERDA)+INFORMACAO2(VARIÁVEL)

+NOME_INFORMACAO3(10POSIÇÕES C/ " " A

ESQUERDA)+TAMANHO_INFORMACAO3(10POSIÇÕES C/ 0 A

ESQUERDA)+INFORMACAO3(VARIÁVEL)

O seu pacote:

HEADER+PAYLOAD

Perceba que os campos do header são fixo e que o payload é variável. Como

você define o tamanho do payload e o tamanho de cada informação dentro do

payload, é possível realizar o parser da string tranquilamente.

Não sei qual sua necessidade, mas considere utilizar webservices, seja

rest, wsdl, ou mesmo JMS.

Depois de definido o layout do seu protocolo, virá a parte mais legal, que

é definir como o seu servidor irá processar essas mensagens.

Nesse ponto sugiro uma lida no livro Programação de rede Unix, Capitulo 30

-> Alternativas de projeto cliente/servidor, irei listar os tópicos, pois

sei que pode te ajudar.

30.4 - > Servidor TCP Interativo

30.5 -> Servidor TCP concorrente, um filho por cliente

30.6 -> Servidor TCP pré-bifurcado, sem bloqueio accept

30.7 -> Servidor TCP pré-bifurcado, bloqueio de arquivo em torno de accept

30.8 -> Servidor TCP pré-bifurcado, bloqueio de thread em torno de accept

30.9 -> Servidor TCP pré-bifurcado, passagem de descritor

30.10 -> Servidor TCP concorrente, um thread por cliente

30.11 -> Servidor TCP pré-threaded, um accept por thread

30.12 -> Servidor TCP pré-threaded, thread principal chama accept

Acima temos exemplos da utilização de forks e threads, no seu caso,

provável que utilize threads e definir como funcionara suas threads/pool de

threads será crucial para a escalabilidade da sua aplicação. Sugiro que

você abstraia a linguagem e se concentre nos conceitos... dessa forma você

irá conseguir desenvolver algo bacana.

O Java - Como programar do Deitel possui exemplos simples de como trabalhar

com sockets/threads, legal para fazer e ver funcionando, mas sinceramente

deixa a desejar e por isso recomendei o Programação de rede Unix como

literatura auxiliar.

Na mesma linha, você pode pesquisar sobre JAVA NIO(caso você possua *muitas

transações* concorrentes) e também se preocupar com a criptografia dos

pacotes... seja ela feita na camada de apresentação ssl/tls ou a nível de

aplicação, seja simétrica ou assimétrica.

Boa sorte! Inveja alheia... queria estar com um problema desses nas mãos

\o/.

[]s

--

Att, Marcelo M. Fleury

Blog - http://marcelomf.blogspot.com/

Slides - http://www.slideshare.net/marcelomf/

"O primeiro dever da inteligência é desconfiar dela mesma." By Einstein

[As partes desta mensagem que não continham texto foram removidas]

[As partes desta mensagem que não continham texto foram removidas]



[As partes desta mensagem que não continham texto foram removidas]

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

Para sair da lista, envie email para: java-br-unsubscribe@yahoogroups.com
Para upload/download de arquivos:
http://www.yahoogroups.com/files/java-brLinks do Yahoo! Grupos

__._,_.___
Atividade nos últimos dias:
Para sair da lista, envie email para: java-br-unsubscribe@yahoogroups.com
Para upload/download de arquivos: http://www.yahoogroups.com/files/java-br
Ofertas HP: ProBook 4430s

Ainda dá tempo de encontrar companhia para passar o Dia dos Namorados!

Ainda dá tempo de encontrar companhia para passar o Dia dos Namorados!
.

__,_._,___

0 comentários:

Pague com LPs do Mister Colibri

Pague com LPs do Mister Colibri
Quer comprar celular,Tablet,pen drive, GPS e muito outros produtos e ainda podendo pagar tudo em LPs ?Pois saiba que isso é possível,basta você visitar o site downloadstotal.com e realizar a sua compra com toda tranquilidade e segurança!!!

Hora

Online

Arquivo do Blog