2009-08-27 12 views
31

Si solo estoy ESCRIBIENDO a un socket en un flujo de salida, ¿alguna vez bloqueará? Solo las lecturas pueden bloquear, ¿verdad? Alguien me dijo que las escrituras pueden bloquear pero solo veo una función de tiempo de espera para el método de lectura de un socket - Socket.setSoTimeout().java socket/output stream escribe: ¿bloquean?

No tiene sentido para mí que una escritura pueda bloquear.

+0

El hecho de que no es una característica de tiempo de espera no es en sí una indicación de que no bloquee. Una indicación de que lo hace es la falta de un valor de retorno: si no bloquea, ¿por qué no devuelve el número de bytes realmente escritos? Otra indicación se da simplemente intentándolo. – EJP

Respuesta

45

Una escritura en un zócalo también puede bloquear, especialmente si es un zócalo TCP. El sistema operativo solo almacenará una cierta cantidad de datos no transmitidos (o transmitidos, pero no reconocidos). Si escribe cosas más rápido de lo que la aplicación remota puede leerlas, el socket eventualmente realizará una copia de seguridad y sus llamadas write se bloquearán.

responder a estas preguntas de seguimiento:

Entonces, ¿hay un mecanismo para establecer un tiempo de espera para esto? No estoy seguro de qué comportamiento hubiera tenido ... ¿tal vez tirar datos si los buffers están llenos? ¿O posiblemente borrar datos más antiguos en el búfer?

No hay ningún mecanismo para configurar un tiempo de espera de escritura en java.net.Socket. Hay un método Socket.setSoTimeout(), pero afecta a accept() y read() llamadas ... y no a write() llamadas. Aparentemente, puedes obtener tiempos de espera de escritura si usas NIO, modo sin bloqueo y Selector, pero esto no es tan útil como podrías imaginar.

Una pila TCP correctamente implementada no descarta datos almacenados a menos que la conexión esté cerrada. Sin embargo, cuando obtiene un tiempo de espera de escritura, no está claro si los datos que se encuentran actualmente en los búferes de nivel de sistema operativo han sido recibidos por el otro extremo ... o no. El otro problema es que no sabe cuánto de los datos de su último write se transfirió realmente a los búferes de pila TCP de nivel del sistema operativo. En ausencia de algún protocolo de nivel de aplicación para resincronizar la secuencia *, lo único seguro después de un tiempo de espera en write es cerrar la conexión.

Por el contrario, si utiliza una toma UDP, las llamadas write() no se bloquearán durante un período de tiempo significativo. Pero la desventaja es que si hay problemas de red o la aplicación remota no se mantiene, los mensajes se dejarán caer sin notificación a ninguno de los extremos. Además, puede encontrar que los mensajes a veces se entregan a la aplicación remota fuera de servicio. Depende de usted (el desarrollador) lidiar con estos problemas.

* Teóricamente es posible hacerlo, pero para la mayoría de las aplicaciones no tiene sentido implementar un mecanismo de resincronización adicional sobre una transmisión TCP/IP ya confiable (hasta un punto). Y si tuviera sentido, también necesitaría tratar con la posibilidad de que la conexión se cerrara ... por lo que sería más simple asumir que cerró.

+0

Entonces, ¿hay un mecanismo para establecer un tiempo de espera para esto? No estoy seguro de qué comportamiento tendría ... ¿tal vez tirar datos si los almacenamientos intermedios están llenos? ¿O posiblemente elimines los datos más antiguos en el búfer? – jbu

+0

¿Hay alguna manera de reproducir esto para probar? Quiero que mi aplicación pueda recuperarse de esto. para esto necesito probar – Zamir

+0

AFAIK, no hay manera general. Pero dependiendo de la naturaleza de su aplicación (por ejemplo, con qué está hablando) hay muchas maneras. Haga una nueva pregunta ... y sea específico. –