style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Bug con Socket y ServerSocket

Lo que suce es que encontre creo un bug en la maquina virtual de java .

Detalles. Tengo un servidor usando ServerSocket, y atiende peticiones de clientes, cada cliente que se conecta es un nuevo Thread. Y lo atiene la clase AtienteSocket que se queda a la espera de comandos, pero se supone que cuando hay un error de entrada /salida debe surgir un error, pero este no lo refleja sino se queda bloqueado :O. ESPERANDO COMANDOS, los pido con un DataInputStream. in.readUTF();

Como provocar ese bug. Ejecutando el cliente en una PC y el server en otro PC. CUando haya hecho la conexion desconecten el cable de red del cliente y veran que no surge ningun error, sino que el sockets refleja como si aun estuviera conectado :O. Tambien surge cuando la PC se queda sin internet repentinamente.

Aqui las clases de trabajo

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Cliente extends Thread {

    private Socket socket;
    private DataInputStream in;
    private DataOutputStream out;

    public Cliente(String ip, int puerto) {
        try {
            socket = new Socket(ip, puerto);
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    @Override
    public void run() {

        try {
            while (true) {
                //Aqui se bloquea hasta que reciba algun texto
                String recibo = in.readUTF();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
    public static void main(String[] args) {
        Cliente c=new Cliente("127.0.0.1", 81);
        c.start();
    }
}

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Servidor extends Thread {

    private ServerSocket servidor;

    public Servidor(int puerto) {
        try {
            servidor = new ServerSocket(puerto);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void run() {
        try {
            while (true) {
                Socket conexion=servidor.accept();
                AtienteSocket atiende=new AtienteSocket(conexion);
                atiende.start();
               
            }
        } catch (Exception e) {
        }
    }
   
    public static void main(String[] args) {
        Servidor servi=new Servidor(81);
        servi.start();
    }
}

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AtienteSocket extends Thread {

    private DataInputStream in;
    private DataOutputStream out;

    public AtienteSocket(Socket socket) {
        try {
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void run() {
        try {
            while (true) {
                System.out.println("Voy a esperar algun comando,"
                        + "mientas me quedo bloqueado!");
                String mensaje=in.readUTF();
                System.out.println("Lei algun mensaje!. Voy de nuevo a la espera!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Se supone que hubo un error");
        }
    }
}

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

normal

Ese es el comportamiento normal de los sockets. Si lo programas en C o en C# o en ObjC o en lo que sea va a pasar lo mismo.

:S

Entonces sel servidor se quedaria esperando comandos inifinitamente :S, ya que ni checando si el socket está cerrado funciona.

Que mal. :(

Alguna solución?

Imagen de ezamudio

timeout

Puedes ponerle un timeout a cada socket. Por default no tienen timeout, así que cuando haces una operación de lectura sobre su InputStream y no hay datos, se queda bloqueado indefinidamente. Pero si le pones timeout al socket, cuando haces una lectura y no hay datos, se bloquea máximo por el tiempo que hayas indicado, y en ese momento se arroja SocketTimeoutException. Ahí puedes revisar si el socket sigue conectado o ya no, para volver al ciclo e intentar leer datos otra vez, o cerrar la conexión.

No funciona :S

Aun asi el socket me dice que no ha sido cerrado

soket.isClosed(); Regresa siempre false.

Es raro

Imagen de ezamudio

es que no se ha caído

Desconectar el cable no necesariamente rompe la conexión, así no funciona TCP. Si lo desconectas unos segundos y lo vuelves a conectar a veces se puede restablecer la conexión, la aplicación ni cuenta se da de la desconexión temporal si el sistema operativo no se lo notifica.

XD

Pero el punto es que aveces una computadora cliente se queda sin internet, y no se regleja en el server. Punto menos para java :(

Imagen de ezamudio

prueba C#

corre, ve y prueba C# para que veas que pasa exactamente lo mismo.

Imagen de bferro

Nada tiene que ver con el lenguaje

Como comenta Enrique, nada tiene que ver con el lenguaje. Es el ciclo de vida del socket como abstracción de programación para trabajar a nivel de transporte. La magia no existe si no hay magos, y los magos somos nosotros.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">