ArrayList i dziwne zachowanie podczas przesyłania

0

Witam, zaobserwowałem dziwne (przynajmniej dla mnie:)) zachowanie związane z arraylist i przesyłaniem danych przez gniazdo.
Najpierw w porgramie klienta dodaje elementy do listy i trzy razy wysyłam to samo. przed czwartym wysłaniem dodaje jeszcze jeden element... ale po wysłaniu nie jest on wyświetlany na serwerze.
Nie rozumiem :F

Serwer:

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

public class serv {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ServerSocket ss = new ServerSocket(7777);
        Socket s = ss.accept();
        if (s != null) {
            ObjectInputStream input = new ObjectInputStream(s.getInputStream());

            for (int i = 0; i < 4; i++) {
                pakiet p = (pakiet) input.readObject();
   
                System.out.println("lista: "+p.lista);
            }
        }
    }
}

Klient:

import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class klient {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("localhost", 7777);
        ObjectOutputStream output = new ObjectOutputStream(s.getOutputStream());

        ArrayList tmp = new ArrayList();
        tmp.add("jan");
        tmp.add("adam");

        for (int i = 0; i < 3; i++) {
            pakiet p = new pakiet();
            p.lista = tmp;
            output.writeObject(p);
        }

        tmp.add("ewa");

        pakiet p = new pakiet();
        p.lista = tmp;
        output.writeObject(p);
    }
}

Pakiet:

import java.io.Serializable;
import java.util.ArrayList;

public class pakiet implements Serializable {
    ArrayList lista;
}
0

Po mojemu para ObjectOutputStream i ObjectInputStream służy do przesłania jednego obiektu, a nie ciągu obiektów. Klasa serv czytała za każdym razem pierwszy wysłany obiekt.
Btw. nieobsługiwanie wyjątków jest bardzo złym zwyczajem.
Klasa serv:

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

public class serv {
    public static void main(String[] args)
    {
        try
        {
        ServerSocket ss = new ServerSocket(7777);
        for(int i=0;i<2;i++)
        {
        Socket s = ss.accept();
        if (s != null)
        {
            ObjectInputStream input = new ObjectInputStream(s.getInputStream());
            pakiet p = (pakiet) input.readObject();
            System.out.println("lista: "+p.lista);
        }
        }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}

Klasa klient:

import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class klient {
    public static void main(String[] args)
    {
        try
        {
        Socket s = new Socket("localhost", 7777);
        ObjectOutputStream output = new ObjectOutputStream(s.getOutputStream());

        ArrayList tmp = new ArrayList();
        tmp.add("jan");
        tmp.add("adam");
        pakiet p = new pakiet();
        p.lista = tmp;
        output.writeObject(p);
        output.close();


        tmp.add("ewa");

        s = new Socket("localhost", 7777);
        output = new ObjectOutputStream(s.getOutputStream());
        p = new pakiet();
        p.lista = tmp;
        output.writeObject(p);
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}

0

Oczywiście, że nieobsługiwanie wyjątków jest złym zwyczajem, ale to tylko przykład pisany na szybko.

ObjectOutputStream i ObjectInputStream służą do przesyłania obiektów, jest nim np. pakiet. Ale na pewno nie do wysłania tylko jednego.
Tworzenie nowego gniazda dla każdej paczki danych nie miałoby zastosowania w praktyce.

Dla potwierdzenia: gdy doda się do klasy pakiet pole składowe typu string i będzie się wysyłać strumień kilka razy, ale za każdym razem z inną zawartością tego pola, serwer wyświetli każdą z nich.

0

Moze chodzi o to: serializacja wysyla za pierwszym razem caly obiekt jak robisz writeObject, a nastepnym razem tylko zapisuje referencje jelsi to ten sam obiekt. Dlatego za pierwszym razem sle wszystko, a za kolejnymi sle tylko referencje do klienta, tamten sprawdza ja, patrzy, ze juz taka pobieral i zwroci to co za pierwszym razem. Aby tego uniknac sluzy metoda ObjectOutputStream.reset() - przeczytaj jej javadoc i bedzie jasne.
To ze ObjectOutputStream sluzy do przeslania jednego obiektu jest niedorzeczne.

0

@:: napisał

To ze ObjectOutputStream sluzy do przeslania jednego obiektu jest niedorzeczne.
Musze się z tym zgodzić [glowa] .

0

@::
Masz rację, dzięki za pomoc i wytłumaczenie!

0

Dziwne zachowanie (jak wyjaśnił ::) było spowodowane tym, że były co prawda tworzone nowe obiekty klasy pakiet, ale nie zmieniała się referencja do składowej lista. Mam pytanie, czy istnieje prosty sposób konstruowania obiektu klasy pakiet, który zmieni referencję lista?
Działa takie coś:

import java.io.Serializable;
import java.util.ArrayList;

public class pakiet implements Serializable 
{
    ArrayList lista=new ArrayList();
    public pakiet(ArrayList l)
    {
        for(int i=0;i<l.size();i++)
           lista.add(l.get(i));
    }
}
//------------------------
        tmp.add("ewa");

        pakiet p = new pakiet(tmp);
        output.writeObject(p);

Wywoływanie metody reset() nie jest konieczne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1