metodos - metodo read java
Cómo identificar el final de InputStream en Java (7)
Estoy tratando de leer bytes del servidor usando el programa Socket, es decir, estoy usando InputStream para leer los bytes. Si paso el tamaño de longitud, puedo leer los bytes, pero no estoy seguro de cuál puede ser la longitud. Entonces no puedo inicializar la matriz de bytes.
También probé while (in.read() != -1)
, while (in.read() != -1)
que el bucle funciona bien cuando se envían los datos, pero la siguiente línea después del bucle no es ejecutable, creo que sigue buscando los datos en la secuencia pero no hay datos Si cierro la conexión del servidor, mi cliente ejecutará la siguiente línea seguida del ciclo.
No estoy seguro de dónde me estoy equivocando?
this.in = socket.getInputStream();
int dataInt = this.in.read();
while(dataInt != -1){
System.out.print(","+i+"--"+dataInt);
i++;
dataInt = this.in.read();
}
System.out.print("End Of loop");
Obtengo el resultado como:
,1--0,2--62,3--96,4--131,5--142,6--1,7--133,8--2,9--16,10--48,11--56,12--1,13--0,14--14,15--128,16--0,17--0,18--0,19--48,20--0,21--0,22--0,23--0,24--0,25--1,26--0,27--0,28--38,29--114,30--23,31--20,32--70,33--3,34--20,35--1,36--133,37--48,38--51,39--49,40--52,41--49,42--55,43--49,44--52,45--52,46--54,47--55,48--50,49--51,50--52,51--48,52--53,53--56,54--51,55--48,56--48,57--57,58--57,59--57,60--57,61--57,62--57,63--57,64--56
Pero no hay salida para: - Fin del ciclo
Por favor guía cómo debo cerrar el ciclo?
Esperamos su respuesta. Agradeciéndoles a todos por adelantado.
Creo que en realidad has respondido tu propia pregunta.
La razón por la que no está saliendo del bucle es que el final de la secuencia de entrada solo ocurre en el extremo del cliente después de que el servidor finaliza su conexión. (O más precisamente, después de que cierra su flujo de salida de socket ... o su equivalente ... y el evento close se propaga al extremo del cliente).
Hasta que ocurra ese evento, es posible que el servidor decida escribir más datos en el socket. Entonces, los bloques de lectura del lado del cliente ... hasta que recibe más datos o ve el evento de protocolo que dice que el servidor se ha cerrado.
(En realidad, otros eventos pueden desbloquear la lectura del cliente, pero todos darán lugar a una IOException
de algún tipo, y probablemente a una secuencia de la que no pueda leer más datos).
Ahora, si no quiere cerrar el servidor ahora porque quiere enviar más cosas al socket más adelante, tendrá que cambiar su protocolo de aplicación para utilizar algún tipo de mecanismo de encuadre. Por ejemplo, el servidor puede enviar un cuadro (o registro, o lo que sea) que consiste en conteo de bytes seguido de la cantidad dada de bytes. Alternativamente, podría usar un valor de byte distinguido o una secuencia de bytes para marcar el final de un cuadro.
En el caso -1, no termina el ciclo. Ponga 65535 en la condición y estoy 99% seguro de que detendrá el ciclo.
while(dataInt != 65535){
System.out.print(","+i+"--"+dataInt);
i++;
dataInt = this.in.read();
}
Está buscando más datos porque nada le dice que no habrá más datos. El otro extremo de la red podría enviar más datos en cualquier momento.
No está claro si está diseñando el protocolo cliente / servidor o simplemente tratando de implementarlo, pero generalmente hay tres formas comunes de detectar el final de un mensaje:
- Cerrar la conexión al final del mensaje
- Poniendo la longitud del mensaje antes de los datos en sí
- Usando un separador; algún valor que nunca ocurrirá en los datos normales (o que siempre se escaparía de alguna manera)
Personalmente prefiero el prefijo de longitud cuando sea posible; hace que el código de lectura sea significativamente más simple, pero aún permite múltiples mensajes en la misma conexión.
(Además, estoy de acuerdo con Daniel en que deberías estar usando la sobrecarga de read
que lee todo un buffer a la vez, en lugar de un solo byte. Esto será mucho más eficiente, pero no cambia fundamentalmente la naturaleza de tu problema actual .)
He tenido un problema similar donde in.read()
simplemente se cuelga al final de los datos en lugar de devolver un -1.
Si no tiene control sobre el código del servidor, ¿hay un marcador confiable que pueda detectar en los datos devueltos (por ejemplo, </html>
) y lo use para finalizar el ciclo de lectura?
De lo socket.setSoTimeout(reasonableValue)
, considere usar socket.setSoTimeout(reasonableValue)
para que al menos su aplicación no se cuelgue para siempre ...
Puede cerrar la secuencia de forma segura después del ciclo while. dataInt
siendo -1 significa que no hay nada más que leer de él.
http://download.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html#read ()
Si el ciclo while no sale, significa que todavía hay datos escritos en el otro extremo de la secuencia. Cierre la corriente en el otro extremo. Si puede publicar el código donde escribe datos para transmitirlos, será útil.
Puedes ejecutar este ejemplo.
Si va a esperar el final de la transmisión, debe cerrarla en el lado de envío para recibir EOF (-1).
Para enviar múltiples mensajes binarios, prefiero enviar la longitud antes del mensaje, ya que permite que el código lea bloques grandes a la vez (es decir, porque sabe cuánto va a obtener).
ServerSocket ss = new ServerSocket(0);
Socket s = new Socket("localhost", ss.getLocalPort());
Socket s2 = ss.accept();
final OutputStream out = s.getOutputStream();
out.write("Hello World!".getBytes());
out.close();
final InputStream in = s2.getInputStream();
for (int b = 0; ((b = in.read()) >= 0);) {
System.out.println(b + " " + (char) b);
}
System.out.println("End of stream.");
s.close();
s2.close();
ss.close();
huellas dactilares
72 H
101 e
108 l
108 l
111 o
32
87 W
111 o
114 r
108 l
100 d
33 !
End of stream.
También tuve el problema de no haber salido del círculo. Mi solución se parecía a esto:
while (in.ready()){
System.out.print(","+i+"--"+dataInt);
i++;
dataInt = this.in.read();
}