Serialization and sending of objects through Socket JAVA

1

Greetings I am doing a project in which I have a ServerSocket where I try to send a serialized object to a Socket with random numbers and the date in which they were generated for the client to operate with them. I have a main (), a ServerHilo (which accepts a maximum of 10 connections) and an object class named Parameters. And on the client side, a class with the client and its object with the Parameters. The problem is that I miss this failure. Could someone help me?

-Project Server -

Main

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package servidorsatelite;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;

/**
 *
 * @author DAM205
 */
public class ServidorSatelite extends Thread {

    static ServerSocket servidor;
    static final int puerto = 6000;
    static int conexionesActuales = 0;
    static Socket tabla[] = new Socket[10];

    static Parametros parametrosEstacion = new Parametros();
    static Parametros parametrosRover = new Parametros();

    Random coordenadaNEstacion = new Random();
    Random coordenadaEEstacion = new Random();
    Random coordenadaNRover = new Random();
    Random coordenadaERover = new Random();

    int numeroNEstacion, numeroEEstacion;
    int numeroNRover, numeroERover;

    Calendar instante;

    public static void main(String[] args) throws IOException {
        servidor = new ServerSocket(puerto);
        System.out.println("- Servidor satélite operativo -");
        System.out.println("-------------------------------\n");

        ServidorSatelite generadorCoordenadas = new ServidorSatelite();
        Thread hiloCoordenadas = new Thread(generadorCoordenadas);
        hiloCoordenadas.start();

        while (conexionesActuales <= 10) {
            Socket s = new Socket();
            try {
                s = servidor.accept();
            } catch (SocketException ns) {
                break;
            }
            tabla[conexionesActuales] = s;
            conexionesActuales++;
            HiloServidor hiloServidor = new HiloServidor(s, parametrosEstacion, parametrosRover);
            hiloServidor.start();
        }

        if(!servidor.isClosed())
            try{
                servidor.close();
            }catch (IOException ioe){
                ioe.printStackTrace();
            }

        System.out.println("Servidor satelite deshabilitado");
        System.out.println("-------------------------------\n");

    }

    public void run() {
        while (true) {
            instante = Calendar.getInstance();
            Date momenActual = instante.getTime();
            parametrosEstacion.setInstante(momenActual);
            parametrosRover.setInstante(momenActual);
            System.out.println(parametrosEstacion.getInstante());

            numeroNEstacion = coordenadaNEstacion.nextInt(50);
            parametrosEstacion.setNumeroN(numeroNEstacion);
            System.out.println("Estación punto N: " + parametrosEstacion.getNumeroN());

            numeroEEstacion = coordenadaEEstacion.nextInt(50);
            parametrosEstacion.setNumeroE(numeroEEstacion);
            System.out.println("Estación punto E: " + parametrosEstacion.getNumeroE());

            numeroNRover = coordenadaERover.nextInt(50);
            parametrosRover.setNumeroN(numeroNRover);
            System.out.println("Rover punto N: " + parametrosRover.getNumeroN());

            numeroERover = coordenadaERover.nextInt(50);
            parametrosRover.setNumeroE(numeroERover);
            System.out.println("Rover punto E: " + parametrosRover.getNumeroE());
            System.out.println("");

            try {
                Thread.sleep(5000);
            } catch (Exception e) {
            }
        }
    }

}

HiloServidor

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package servidorsatelite;

import java.io.*;
import java.net.*;

/**
 *
 * @author DAM205
 */
public class HiloServidor extends Thread {

    Socket socket = null;
    Parametros paramEstacion = new Parametros();
    Parametros paramRover = new Parametros();

    ObjectOutputStream fsalida;

    public HiloServidor(Socket s, Parametros estacion, Parametros rover) {
        socket = s;
        paramEstacion = estacion;
        paramRover = rover;
    }

    public void run() {
        while (true) {
            try {
                System.out.println("Comunico con: " + socket.toString());
                EnviarObjetos(paramEstacion);
                try {
                    Thread.sleep(5000);
                } catch (Exception e) {
                }
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
    }

    private void EnviarObjetos(Parametros paramEstacion) throws IOException {
        int i;
        for (i = 0; i < ServidorSatelite.conexionesActuales; i++) {
            Socket s1 = ServidorSatelite.tabla[i];

            try {
                fsalida = new ObjectOutputStream(s1.getOutputStream());
                fsalida.writeObject(paramEstacion);
            } catch (SocketException se) {
                se.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Parameters

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package servidorsatelite;

import java.io.Serializable;
import java.util.Date;

@SuppressWarnings("serial")

/**
 *
 * @author DAM205
 */
public class Parametros implements Serializable {

    int numeroN, numeroE;
    Date instante;

    public Parametros() {
        super();
    }

    public Parametros(int numeroN, int numeroE, Date instante) {
        super();
        this.numeroN = numeroN;
        this.numeroE = numeroE;
        this.instante = instante;
    }

    public int getNumeroN() {
        return numeroN;
    }

    public void setNumeroN(int numeroN) {
        this.numeroN = numeroN;
    }

    public int getNumeroE() {
        return numeroE;
    }

    public void setNumeroE(int numeroE) {
        this.numeroE = numeroE;
    }

    public Date getInstante() {
        return instante;
    }

    public void setInstante(Date instante) {
        this.instante = instante;
    }
}

-Project Client -

Main

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package servidorclientebase;

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

/**
 *
 * @author iberd
 */
public class ServidorClienteBase {

    /**
     * @param args the command line arguments
     * @throws java.io.IOException
     * @throws java.lang.ClassNotFoundException
     */
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String host = "localhost";
        int puerto = 6000;
        Parametros dato = new Parametros();

        System.out.println("Estación base operativa");
        System.out.println("-----------------------\n");
        Socket cliente = new Socket(host, puerto);

        //Flujo entrada para objetos
        ObjectInputStream perEnt = new ObjectInputStream(cliente.getInputStream());

        while (true){
        //Se recibe un objeto
            dato = (Parametros) perEnt.readObject();
        }
    }

}

Parameters

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package servidorclientebase;

import java.io.Serializable;
import java.util.Date;

@SuppressWarnings("serial")

/**
 *
 * @author DAM205
 */
public class Parametros implements Serializable {

    int numeroN, numeroE;
    Date instante;

    public Parametros() {
        super();
    }

    public Parametros(int numeroN, int numeroE, Date instante) {
        super();
        this.numeroN = numeroN;
        this.numeroE = numeroE;
        this.instante = instante;
    }

    public int getNumeroN() {
        return numeroN;
    }

    public void setNumeroN(int numeroN) {
        this.numeroN = numeroN;
    }

    public int getNumeroE() {
        return numeroE;
    }

    public void setNumeroE(int numeroE) {
        this.numeroE = numeroE;
    }

    public Date getInstante() {
        return instante;
    }

    public void setInstante(Date instante) {
        this.instante = instante;
    }

}

When I start the server and the client I get the following errors: Client

Server

    
asked by Eduardo 26.02.2017 в 13:22
source

2 answers

1

The Parameters class is defined in the two packages. Although the definition is identical, Java interprets that they are two different classes. Therefore, you are serializing an object of the servername.Parameters class and trying to deserialize it as if it were from the clientbasebase.Parameters class. Indicating that you use the Parameters class of the servername package solves the problem:

public static void main(String[] args) throws IOException, ClassNotFoundException {
    String host = "localhost";
    int puerto = 6000;
    servidorsatelite.Parametros dato = new servidorsatelite.Parametros();

    System.out.println("Estación base operativa");
    System.out.println("-----------------------\n");
    Socket cliente = new Socket(host, puerto);

    //Flujo entrada para objetos
    ObjectInputStream perEnt = new ObjectInputStream(cliente.getInputStream());

    while (true){
    //Se recibe un objeto
        dato = (servidorsatelite.Parametros) perEnt.readObject();
    }
    
answered by 26.02.2017 / 15:12
source
0

A cast to a class in Java after receiving it in a deserialisation only works if:

  • The canonical name of the class is the same ( com.miapp.paquete.Clase )
  • The serial number (involving the class version) is the same, or there is no
  • The deserialisation is compatible with the object to which the cast is made.

The canonical name is what comes out in objeto.getClass().getCanonicalName(); .

To add to the correct answer, I would recommend in a case of object transfer between applications in distributed systems to follow the following practices:

  • Define all shared types in a library as a model.
  • implement the serial number of the classes that are transmitted
  • add the library as a dependency to both projects.

To receive the objects, it is recommended to save them in a basic object first and then check the type with instanceof .

// asumiendo ObjectInputStream ois
Object o = ois.readObject();
if (o instanceof Parametros){
    ...
} else {
    // manejo de envío de objeto desconocido
}

That also prevents someone from attacking your system with random objects to cause exceptions. Performing an insecure cast on objects received over TCP can cause security vulnerabilities similar to missing escape data from users in SQL queries, in the worst case.

In your case, "only" the application will fall.

    
answered by 26.02.2017 в 22:43