bem, estou programando um programa simples que utiliza um client socket (java.net.Socket) e um java.io.DataInputStream para receber dados…
para ler os dados utilizo o metodo read da class DataInputStream, porem, como todos sabem ele é bloqueante!
queria saber se existe alguma maneira de, forca o retorno do metodo read, sem que ele receba um dado?
obrigado
Não.
Para isso, você deve monitorar você mesmo o stream através do método available(), e não fazer a leitura de mais bytes do que estiverem disponíveis.
Ou então, usar os métodos do SocketChannel. Nele vc carrega os dados num ByteBuffer, para leitura posterior (com gets convenientes como o do DataInputStream) e pode especificar um tempo máximo para o bloqueio, caso os dados não estejam lá.
Se quiser mesmo poder de fogo, pode também usar Selectors, mas não precisa de tanta complicação. Para mais informações:
http://www.developer.com/java/article.php/1449271
http://exampledepot.com/egs/java.nio/ReadSocket.html?l=rel
http://exampledepot.com/egs/java.nio/NbClientSocket.html?l=rel
http://java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/Channel.html
obrigado ViniGodoy
usei o metodo available() mesmo,
ainda preciso entender melhor como o java funciona para tentar alguma coisa mais avançada que isso
e alias, tenho outra pergunta :roll:
quais vantagens em usar isso:
entrada = new DataInputStream( new BufferedInputStream( socket.getInputStream() ) );
em vez de simplesmente isso:
entrada = socket.getInputStream();
pelo o que eu entendi do metodo, usando o primeiro caso, ele criara um buffer, mais… o que acontece “detro” do java?
quais vantagens tem em usar o primeiro caso?
fiquei testando aqui em casa, e nao senti diferenca
obrigado mais uma vez
Eu recomendo fortemente que você aprenda a usar o SocketChannel, nem que seja do jeito feijão com arroz. É mais fácil do que usar os streams… e mais eficiente também.
A diferença é a que você falou. No primeiro caso, cria-se um buffer, que nada mais é do que um array, onde os bytes são gravados. A diferença é maior no caso de arquivos, experimente fazer um teste com eles. Isso porque uma leitura mais continua do arquivo otimiza o uso do HD.
Então, mesmo que você faça a leitura de um só byte (com read()) o BufferedInputStream irá ler um bloco inteiro, do tamanho do buffer e te fornecer um byte só. No segundo byte requisitado, não existe leitura, ele te fornece o segundo byte do buffer. Quando o buffer acaba, ele lê outro bloco, do tamanho do buffer.
A gravação ocorre da mesma forma, mas no sentido inverso. Você acumula os dados a serem gravados num buffer e, quando o buffer está cheio, ele é enviado para o arquivo ou socket de uma só vez. Por isso existem comandos como flush(), que exigem que a descarga dos buffers seja feita. O TCP/IP tem esse mecanismo automático, mas você pode desliga-lo usando algumas opções do Socket (setTCPNoDelay(true), se eu não me engano).
Se você é tão curioso à respeito do que ocorre por baixo dos panos, dá uma lida no padrão Decorator (que é o dos InputStreams) e abra o código fonte dessas classes e tente entender. Eu já fiz isso várias vezes e, na maioria dos casos, não é tão difícil quanto parece.