Avatar billede cannes Nybegynder
22. maj 2003 - 12:21 Der er 6 kommentarer og
1 løsning

Problemer med at overføre Vector gennem sockets.

Jeg har en concurrent server:

import java.net.ServerSocket;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.BindException;
import java.net.Socket;
import java.net.SocketException;
import java.io.IOException;
import java.util.Vector;

class ServerKommunikation implements Runnable
{
    public static final int DEFAULT_PORT = 4650;
    private OnlineBruger bruger, temp;
    private Socket forbindelse;
    private ServerSocket server;
    private Vector availablePlayers = new Vector();

    ServerKommunikation ()
    {
        try
        {
            server = new ServerSocket (DEFAULT_PORT);
            System.out.println("server socket oprettet");
        }
        catch (IOException ioe)
        {
            System.err.println("Kan ikke lave serversocket");
            System.err.println(ioe);
        }
    }

    public void run ()
    {
        while (true)
        {
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException ie)
            {
                System.err.println("InterruptedException i serverKommunikation");
                System.err.println(ie);
            }
            try
            {
                forbindelse = server.accept();
                bruger = new OnlineBruger (forbindelse, this, availablePlayers);
                bruger.start();
            }
            catch (IOException ioe)
            {
                System.err.println("IOException i serverKommunikation");
                System.err.println(ioe);
            }
        }
    }
}

Denne deler forbindelesen ud på følgende tråde:

import java.net.ServerSocket;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.BindException;
import java.net.Socket;
import java.net.SocketException;
import java.io.IOException;
import java.util.Vector;

class OnlineBruger extends Thread
{
    private String navn;
    private char status = 'a';
    private ObjectInputStream input;
    private ObjectOutputStream output;
    private DataFraServer dataFraServer;
    private DataTilServer dataTilServer;
    private Socket forbindelse;
    private boolean connected = true;
    private ServerKommunikation com;
    private Vector availablePlayers;
    private boolean statusChanged = true;

    OnlineBruger (String navn)
    {
        this.navn = navn;
    }

    OnlineBruger (Socket forbindelse, ServerKommunikation com, Vector availablePlayers)
    {
        this.forbindelse = forbindelse;
        this.com = com;
        this.availablePlayers = availablePlayers;
    }

    public String getNavn()
    {
        return navn;
    }

    public char getStatus()
    {
        return status;
    }

    public Vector getAvailablePlayers()
    {
        return availablePlayers;
    }

    public void setAvailablePlayers (Vector availablePlayers)
    {
        this.availablePlayers = availablePlayers;
    }

    public void setStatus (char status)
    {
        this.status = status;
        statusChanged = true;
    }

    public void setConnected (boolean connected)
    {
        this.connected = connected;
    }

    public void run ()
    {
        dataTilServer = new DataTilServer();
        try
        {
            input = new ObjectInputStream(forbindelse.getInputStream());
            output = new ObjectOutputStream (forbindelse.getOutputStream());
        }
        catch (SocketException ex)
        {
            System.err.println("Forbindelse med klienten afbrudt.");
            setConnected (false);
        }
        catch (IOException IOEx)
        {
            System.err.println("IO exception");
            System.err.println(IOEx);
        }
        while (connected)
        {
            if (statusChanged)
            {
                if (status == 'a' && navn != null)
                {
                    availablePlayers.add(navn);
                    System.out.println(navn + " added");
                }
                if (status == 'u')
                {
                    for (int i = 0; i < availablePlayers.size(); i++)
                    {
                        if (((String) availablePlayers.get(i)).equals(navn))
                        {
                            availablePlayers.remove(i);
                            break;
                        }
                    }
                }
                statusChanged = false;
            }
            try
            {
                this.sleep(1000);
            }
            catch (InterruptedException ie)
            {

            }
            try
            {
                dataTilServer = (DataTilServer) input.readObject();
                try
                {
                    if (navn == null)
                    {
                        statusChanged = true;
                    }
                    navn = dataTilServer.getBrugernavn();
                }
                catch (NullPointerException npe)
                {
                    System.err.println("NullPointerException" + npe);// ingen data modtaget
                }
            }

            catch (ClassNotFoundException cnfe)
            {
                System.out.println("Problemer med input fra klient");
            }
            catch (NullPointerException npe)
            {
                System.err.println("NullPointerException" + npe);
            }
            catch (Exception e)
            {
                System.err.println("Exception" + e);
            }
            try
            {
                dataFraServer = new DataFraServer(availablePlayers);
                output.writeObject(dataFraServer);
                output.flush();
            }
            catch (NullPointerException npe)
            {
                System.err.println("NullPointerEx omking 145 i online bruger" + npe);
            }
            catch (IOException ioe)
            {
                System.err.println("IOException omkring linie 145 i online bruger" + ioe);
                setConnected(false);
            }
        }
    }
}

De objekter der bliver sendt igennem den ene og den anden vej ser således ud:

import java.io.Serializable;
import java.util.Hashtable;
import java.util.Vector;

class DataFraServer implements Serializable
{
    private Vector availablePlayers;

    DataFraServer (Vector avp)
    {
        availablePlayers = avp;
        System.out.println(availablePlayers + " Konstruktion");
    }

    DataFraServer ()
    {

    }

    public Vector getAvailablePlayers ()
    {
        System.out.println(availablePlayers + " Recieval");
        return availablePlayers;
    }
}

og:

import java.io.Serializable;

class DataTilServer  implements Serializable
{
    private String brugernavn;
    private Traek træk;

    DataTilServer (String brugernavn, Traek træk)
    {
        this.brugernavn = brugernavn;
        this.træk = træk;
    }

    DataTilServer ()
    {

    }

    public String getBrugernavn ()
    {
        return brugernavn;
    }

    public Traek getTræk()
    {
        return træk;
    }
}

Klient delen modtager og sender fra:

import java.net.Socket;
import java.net.UnknownHostException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.util.Vector;

class KlientKommunikation implements Runnable
{
    public static final String DEFAULT_HOST = "127.0.0.1";
        // loopback, denne maskine
    public static final int DEFAULT_PORT = 4650;
    public static String host;
    public static int port;
    private boolean connected = false;
    public static String brugernavn;
    private DataFraServer dataFraServer = new DataFraServer();
    private DataTilServer dataTilServer;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private Brugergraenseflade bgf;
    private Vector players = new Vector();

    private Traek træk = null;

    KlientKommunikation (String brugernavn, String host, int port, Brugergraenseflade bgf)
    {
        this.host = host;
        this.port = port;
        this.brugernavn = brugernavn;
        this.bgf = bgf;
        connected = true;
    }

    public void run ()
    {
        try
        {
            Socket sock = new Socket(host, port);
            output = new ObjectOutputStream (sock.getOutputStream());
            input = new ObjectInputStream(sock.getInputStream());
            System.out.println("klient run startet");
        }
        catch (UnknownHostException UnHoEx)
        { // new Socket
            System.err.println("Kan ikke finde server " + host + " port " + port);
            System.err.println(UnHoEx);
        }
        catch (ConnectException ex)
        { // new Socket
            System.err.println("Kan ikke forbinde til server: " + host);
            System.err.println("server kører muligvis ikke");
            System.err.println(ex);
        }
        catch (NoRouteToHostException ex)
        { // new Socket
            System.err.println("Kan ikke forbinde til server: " + host);
            System.err.println("firewall forhindrer muligvis forbindelse");
            System.err.println(ex);
        }
        catch (IOException IOex)
          { // getInputStream
              System.err.println("IOException kastet");
              System.err.println(IOex);
          }
        while (connected)
        {
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
            }
            try
            {
                træk = bgf.getTræk();
            }
            catch (NullPointerException npe)
            {
            }
            try
            {
                dataTilServer = new DataTilServer(brugernavn, træk);
                output.writeObject(dataTilServer);
            }
            catch (IOException ioe)
            {
                System.err.println("IOException i klient kom");
                System.err.println(ioe);
            }
            catch (NullPointerException npe)
            {
                System.err.println("NullPointerException kastet omkring linie 90");
                System.err.println(npe);
            }
            try
            {
                dataFraServer = (DataFraServer) input.readObject();
                try
                {
                    players = dataFraServer.getAvailablePlayers();
                }
                catch (NullPointerException npe)
                {
                    System.out.println("NullPointerException i klientcom linie 106: " + npe);
                }
                bgf.setPlayers(players);
                bgf.setTræk(null);
              }
              catch (NullPointerException npe)
              {/*
                System.err.println("NullPointerException i klientKommunikation");
                System.err.println(npe);*/
            }
            catch (IOException IOex)
            { // getInputStream
                System.err.println("Noget galt med getInputStream.");
                System.err.println(IOex);
            }
            catch (Exception e)
            {
                System.out.println("Exception kastet" + e);
            }
        }
    }
    public void setTræk (Traek træk)
    {
        this.træk = træk;
    }
}
og dataene bliver så sendt til brugergrænsefladen som viser dem... problemet er bare at den vector (availablePlayers) Jeg sender igennem ikke er den samme som den jeg modtager.
Hvis der er 2 klienter logget på serveren med navn sat til henholdsvis player1 og player2 modtager den første klient en tom Vector og den anden klient en Vector indeholdende (player1) Og det er selv om udskrift af vectoren inden den bliver sendt fra serveren viser at den indeholder (player1, player2) Hvad sker der??
Avatar billede disky Nybegynder
22. maj 2003 - 12:33 #1
prøv at indsæt debug information på serveren og se hvad der bliver sendt der, og det samme på client niveau.

p.s. Skitser lige hvad dit program skal, tager årtier at sætte sig ind i udokumenteret kode
Avatar billede cannes Nybegynder
22. maj 2003 - 12:48 #2
Har jeg allerede gjort Det er det der står allernederst. Når jeg opretter objekter af typen DataFraServer med en Vector availablePlayers skriver jeg den ud her indeholder den i mit eksempel (player1, player2)
Når jeg modtager DataFraServer objekterne hos klienterne indeholder vectoren ikke længere det samme.

Det hele systemet handler om er en skak server/klient. Brugerne logger på serveren og kan så udfordre hinanden til skak. Når en bruger logger på serveren bliver vedkommendes navn lagt ind i den omtalte vector som hvert sekund bliver sendt til alle klienter.
Jeg poster lige koden igen, men fjerner alt det der er uvedkommende for problemet.
Serveren:

class ServerKommunikation implements Runnable
{
private Socket forbindelse;
    private ServerSocket server;
    private Vector availablePlayers = new Vector();

    ServerKommunikation ()
    {
        try
        {
            server = new ServerSocket (DEFAULT_PORT);
            System.out.println("server socket oprettet");
        }
.
.
.
public void run ()
    {
        while (true)
        {
            try
            {
                Thread.sleep(1000);
            }
.
.
.
            try
            {
                forbindelse = server.accept();
                bruger = new OnlineBruger (forbindelse, this, availablePlayers);
                bruger.start();
            }
}

Den enkelte forbindelse:

class OnlineBruger extends Thread
{
    private String navn;
    private char status = 'a';
    private ObjectInputStream input;
    private ObjectOutputStream output;
    private DataFraServer dataFraServer;
    private DataTilServer dataTilServer;
    private Socket forbindelse;
    private boolean connected = true;
    private ServerKommunikation com;
    private Vector availablePlayers;
    private boolean statusChanged = true;

OnlineBruger (Socket forbindelse, ServerKommunikation com, Vector availablePlayers)
    {
        this.forbindelse = forbindelse;
        this.com = com;
        this.availablePlayers = availablePlayers;
    }
.
.
.
public void run ()
    {
        dataTilServer = new DataTilServer();
        try
        {
            input = new ObjectInputStream(forbindelse.getInputStream());
            output = new ObjectOutputStream (forbindelse.getOutputStream());
        }
.
.
.
while (connected)
        {
            if (statusChanged)
            {
                if (status == 'a' && navn != null)
                {
                    availablePlayers.add(navn);
                    System.out.println(navn + " added");
                }
.
.
.
try
            {
                this.sleep(1000);
            }
.
.
.
try
            {
                dataTilServer = (DataTilServer) input.readObject();
                try
                {
                    if (navn == null)
                    {
                        statusChanged = true;
                    }
                    navn = dataTilServer.getBrugernavn();
                }
.
.
.
try
            {
                dataFraServer = new DataFraServer(availablePlayers);
                output.writeObject(dataFraServer);
                output.flush();
            }
}

Klienten modtager her:

class KlientKommunikation implements Runnable
{
    public static final String DEFAULT_HOST = "127.0.0.1";
        // loopback, denne maskine
    public static final int DEFAULT_PORT = 4650;
    public static String host;
    public static int port;
    private boolean connected = false;
    public static String brugernavn;
    private DataFraServer dataFraServer = new DataFraServer();
    private DataTilServer dataTilServer;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private Brugergraenseflade bgf;
    private Vector players = new Vector();

    private Traek træk = null;

    KlientKommunikation (String brugernavn, String host, int port, Brugergraenseflade bgf)
    {
        this.host = host;
        this.port = port;
        this.brugernavn = brugernavn;
        this.bgf = bgf;
        connected = true;
    }

    public void run ()
    {
        try
        {
            Socket sock = new Socket(host, port);
            output = new ObjectOutputStream (sock.getOutputStream());
            input = new ObjectInputStream(sock.getInputStream());
        }
.
.
.
while (connected)
        {
            try
            {
                Thread.sleep(1000);
            }
.
.
.
try
            {
                dataTilServer = new DataTilServer(brugernavn, træk);
                output.writeObject(dataTilServer);
            }
.
.
.
try
            {
                dataFraServer = (DataFraServer) input.readObject();
                try
                {
                    players = dataFraServer.getAvailablePlayers();
                }
.
.
.
}

De objekter der bliver sendt frem og tilbage ser således ud her viser jeg kun dem der kommer FRA server TIL klient da det er dem der er problemer med:

import java.io.Serializable;
import java.util.Hashtable;
import java.util.Vector;

class DataFraServer implements Serializable
{
    private Vector availablePlayers;

    DataFraServer (Vector avp)
    {
        availablePlayers = avp;
        System.out.println(availablePlayers + " Konstruktion");
    }

    DataFraServer ()
    {

    }

    public Vector getAvailablePlayers ()
    {
        System.out.println(availablePlayers + " Recieval");
        return availablePlayers;
    }
}
Avatar billede disky Nybegynder
22. maj 2003 - 12:52 #3
og du sender objekterne til hver sin port til hver sin client ?
Avatar billede cannes Nybegynder
22. maj 2003 - 12:59 #4
Forbindelserne bliver oprettet gennem port (4650), når man opretter sådan en forbindelse bliver man jo i virkeligheden tildelt en hel ny "hemmelig" port hvor der bliver kommunikeret igennem så den primære port (4650) er parat til at modtage nye forbindelser. Hver gang en klient opretter en forbindelse til serveren bliver der oprettet et OnlineBruger objekt til at håndtere forbindelsen til den ene klient, dvs. hvis der er 4 klienter logget på serveren er der 4 OnlineBruger objekter der hver udfører kommunikation med de 4 objekter. I mit eksempel med 2 klienter viser udskrift fra de 2 OnlineBruger objekter at lige inden den sender DataFraServer objekter gennem socket følgende: "[Player1, Player2]Konstruktion"
Klienten Player1 modtager så et DataFraServer objekt hvor udskriften af availablePlayers Vectoren giver: "[]Recieval"
Klienten Player2 modtager et DataFraServer objekt med udskrift af vectoren: "[Player1]Recieval" jænvfør koden ligeoven over din seneste kommentar
Avatar billede arne_v Ekspert
22. maj 2003 - 13:03 #5
Prøv og erstat:

    dataFraServer = new DataFraServer(availablePlayers);

med:

synchronized (availablePlayers) {
    dataFraServer = new DataFraServer(availablePlayers);
}

og erstat:


    DataFraServer (Vector avp)
    {
        availablePlayers = avp;
    }

med:

    DataFraServer (Vector avp)
    {
        availablePlayers = (Vector)avp.clone();
    }
Avatar billede arne_v Ekspert
22. maj 2003 - 13:03 #6
Det er farligt at gemme en referance til noget i en multi-threaded
context.
Avatar billede cannes Nybegynder
22. maj 2003 - 13:12 #7
Det virker. Tak
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester