Lentidão em socket  XML
Índice dos Fóruns » Java Básico
Autor Mensagem
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

Boa tarde,

Estou com um problema em meus sockets, em resumo: lentidão.
Eu faço conexão com ele, e envio básicamente imagens, e alguns comandos curtos do protocolo que criei, acredito que a lentidão está na hora de enviar a imagem, derrepente é muito dado.

Estou utilizando socket TCP. Até mesmo na rede local fica lento, o que vocês me sugerem? Alterar meu protocolo para UDP(queria fazer isso somente se não existisse outra forma mesmo)? ou existe outra forma de compactar melhor as imagens? eu já compactei usando o gzip, eu gero um png, gero o base64 e zipo, ele diminui cerca de 50%.

Obrigado desde já!

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

a) Qual é a velocidade da sua rede local?
b) Você já checou se os pacotes TCP estão vindo "cheios" ou não (use um analisador de protocolo, como o Network Monitor no Windows ou o Ethereal no Linux?) Isso pode estar ocorrendo porque você está enviando os dados 1 byte de cada vez (por exemplo), em vez de usar buffers maiores.
c) E só em último caso é que é desejável ficar efetuando compressão de dados. O correto é não enviar dados que você já enviou (ou seja, áreas da tela que não foram modificadas não devem ser reenviadas).
[WWW]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

E não, UDP não vai deixar seu processamento mais rápido. Ele pode ser útil se você precisa fazer um broadcast, por exemplo, mas se você simplesmente vai usar uma conexão ponto-a-ponto, é melhor usar TCP, para não ter de se matar com mensagens perdidas.
[WWW]
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

thiagol:
Então, minha rede local é normal, cabeada, 10/100/1000.
Só que a conexão não é ponto a ponto, na verdade tenho uma espécia de HUB que gerencia isso, todos se conectam ao hub, depois envio os dados para o cara certo.
Usando o tcp pelo que pude notar ele envia tudo de uma vez não em byte por byte.
Na hora de enviar, eu dou um println no canal de saída enviando uma string. na hora da leitura eu faço um loop percorrendo todos o que veio do canal de entrada, e adicionando em uma string. Seria dessa forma mesmo, ou tem como otimizar isto?
Agora não se minha imagem que quero enviar é grande demais, ou se o protocolo é lento, eu só sei que UDP seria mais rápido, só que com perdas, mas tu dissestes que não é bom, que seria bom pra broadcast, mas e agora?
Obrigado

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
king_of_gods
JavaTeenager

Membro desde: 28/03/2007 14:28:11
Mensagens: 185
Offline

thiagofesta wrote:Seria dessa forma mesmo, ou tem como otimizar isto?


Coloca uma thread escutando o canal, vai evitar da sua aplicação ficar em loop. E é mais seguro.

thiagofesta wrote:Agora não se minha imagem que quero enviar é grande demais, ou se o protocolo é lento, eu só sei que UDP seria mais rápido, só que com perdas, mas tu dissestes que não é bom, que seria bom pra broadcast, mas e agora?


Começe enviando mensagens de textos como Oi, Olá, Tudo bem. Se houver uma diferença de tempo brutal, pode ser alguma coisa na rede ou na aplicação.
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

King_of_gods:
Eu uso uma thread para ler o socket.

eu ja testei pelo telnet o meu soket como você disse, é instântaneo, não da para notar nenhuma lentidão.

Acho que é na hora de enviar as imagens...

Obrigado!

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline


Na hora de enviar, eu dou um println no canal de saída enviando uma string. na hora da leitura eu faço um loop percorrendo todos o que veio do canal de entrada, e adicionando em uma string. Seria dessa forma mesmo, ou tem como otimizar isto?


Pelamordedeus, não use sockets em "modo texto".
Repita comigo e prometa para mim: nunca mais vou usar sockets em "modo texto".

Use um DataInput/OutputStream e envie o comprimento dos dados, depois a mensagem.

Só com o fato de você ter de mandar em modo texto (e passando para Base-64) já está desperdiçando um monte de banda.

Adicionar em uma string? Com "+=" ? Isso está comendo 110% da sua CPU já que isso é um verdadeiro veneno. Use uma StringBuilder ou StringBuffer se você ainda insistir em usar strings.
[WWW]
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

thiagol:
De uma olhada como é meu metódo de enviar e de receber dados:

Escrevendo no socket:


Lendo o socket:


O problema então está no meu socket, não em enviar minha imagem em base64?

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

a) Ler um caracter de cada vez? Argh
b) Uma forma besta de enviar dados via socket é encapsulá-lo em um DataOutputStream/DataInputStream. Se você vai mandar uma imagem (um array de bytes de 1 MB por exemplo), é muito mais rápido fazer algo como:
- Mandar 4 bytes de comprimento (com writeInt
- Mandar os dados (com write

e para receber, ler os dados com readInt e read
[WWW]
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

thiagol:
Certo, mas como ficaria o meu envio?
Vou ter que dar um loop, e ir mandando cada byte? não fica muito lento assim?
E para ler seria a mesma coisa (basicamente, faz um loop e lê todos, e vai deixando em uma string?)

Obrigado pela ajuda!

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

Não é para mandar um byte de cada vez, nem para usar essas classes que terminam com "Reader" ou "Writer".
Até indiquei quais são os métodos que você tem de usar. Não é para mandar um byte de cada vez; mande a imagem completa de uma vez.
[WWW]
KWill
Virtual Machine Man
[Avatar]

Membro desde: 18/09/2006 10:05:46
Mensagens: 609
Offline

Apóio a sugestão do thingol, melhor parar de usar um protocolo de controle orientado a comandos de texto. Bote um DataOutputStream numa ponta e um DataInputStream na outra ponta e fique mandando/recebendo comandos via um protocolo de controle através de writeInt, writeShort, writeLong, readInt, readShort, readLong, etc.

Inté.

"Só estou certo de que não possuo outras certezas" - KWill
"Não penso, mas Googlo, logo existo!" - Geração Copy-Cola
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

Agora entendi...
eu dou la um DataOutputStream(socket.getOutu...).write(Arraay de bytes da minha String).

Mas e a leitura, como seria? o read retorna um inteiro.

Desculpem minha ignorância, sou leigo ainda em java, sei muito pouco.

Obrigado

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

Você lê a quantidade de bytes a serem lidos com readInt, e lê os bytes restantes com read. Por favor, leia a documentação que lhe indiquei.
[WWW]
thiagofesta
JavaGuru
[Avatar]

Membro desde: 19/12/2007 10:42:11
Mensagens: 233
Offline

thiagol:
Obrigado, mas usei o metódo readLine do inputStream para capturar o que vem, pode ser?

Obrigado

"É melhor calar-se e deixar que as pessoas pensem que você é tolo, do que falar e acabar com a dúvida"
Abraham Lincoln
[WWW] [Yahoo!] [MSN]
 
Índice dos Fóruns » Java Básico
Ir para:   
Powered by JForum 2.1.8 © JForum Team