Avatar billede gon Nybegynder
24. september 2007 - 11:14 Der er 9 kommentarer og
1 løsning

ObjectStreams (input/output) og tråde

Hejsa alle eksperter. Jeg er ved at lave et miniprojekt under min datamatikeruddannelse og har i den forbindelse brug for lidt hjælp.
Et af kravene er at applikationen anvender en tråd hos klienten til at håndtere data og hver klient får en seperat tråd hos serveren.
Anyways - problemet er, at mine klienter aldrig får oprettet deres ObjectInputStream på trods af, at der er forbindelse til serveren og denne har oprettet dens ObjectOutputStream.
Jeg har kun vedlagt de tråde der oprettes af klient/server - selve applikationen kan ikke noget endnu.

Note til server: denne har i main-metoden en simpel while løkke som tager imod clienter på en ventende ServerSocket (rettere: socket = serversocket.accept()) og giver denne videre til tråden.

Jeg håber i kan hjælpe mig - er det en deadlock der opstår og i så fald, hvordan kan jeg afhjælpe det ?
Jeg har sat pointene lidt højt da der er en del kode, der skal kigges igennem.
----------Kode Klient
/**
* @author ilm
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/

package client;

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

public class PacketHandler implements Runnable {

    protected String host;
    protected String requestString;
    protected int port;
    protected ObjectInputStream dataIn;
    protected ObjectOutputStream dataOut;
    protected Thread listener = null;
    Socket socket;
    boolean Stopped = false;

    public PacketHandler(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public synchronized void start() throws IOException {

        {
            socket = new Socket(host, port);
            if (listener == null) {
                try {
                    dataOut = new ObjectOutputStream(socket.getOutputStream());
                    dataIn = new ObjectInputStream(socket.getInputStream());

                } catch (IOException ex) {
                    System.out
                            .println("Der skete en IOException i packethandler.java");
                    socket.close();
                    throw ex;
                }
            }
        }
    }

    public synchronized void stop() throws IOException {
        if (listener != null) {
            Stopped = true;
            dataOut.close();
            dataIn.close();
            listener = null;
        }
    }

    public synchronized void run() {
        try {
            while (!Stopped) {
                //kommenteret væk for at få skidtet til at virke med en streng først.
                // ServerTilKlientPakke s2kpakke = (ServerTilKlientPakke)
                // dataIn.readObject();
                // System.out.println(s2kpakke.getHandling());
               
                // send String
                send();

            }

        } catch (IOException ex) {
            if (!Stopped) {
                System.out.println(ex);
            }
        }
    }

    public synchronized void send() throws IOException {
        try {
            dataOut.writeObject("dette er en pakke");
            dataOut.flush();
        } catch (Exception e) {
            System.out.println(e);
        }
        ;
    }
}


------------- Kode Server -------------------

/*
* Java Network Programming, Second Edition
* Merlin Hughes, Michael Shoffner, Derek Hamner
* Manning Publications Company; ISBN 188477749X
*
* http://nitric.com/jnp/
*
* Copyright (c) 1997-1999 Merlin Hughes, Michael Shoffner, Derek Hamner;
* all rights reserved; see license.txt for details.
*/

package server;

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

import client.KlientTilServerPakke;
import client.ServerTilKlientPakke;

public class SpillerHandler implements Runnable {

    protected Socket socket;
    protected ObjectInputStream dataIn;
    protected ObjectOutputStream dataOut;
    protected Thread listener;
    protected ArrayList handlers = new ArrayList();

    public SpillerHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            handlers.add(this);
            KlientTilServerPakke nyPakke = null;
            String message = "Her skal vi sige noget.";
            while (!Thread.interrupted()) {
                if (dataIn.readObject() != null) {
                    // nyPakke = (KlientTilServerPakke) dataIn.readObject();

                    String testmodtaget = (String) dataIn.readObject();
                    System.out.println(testmodtaget);
                    //send en streng istedet for.
                    // ServerTilKlientPakke returPakke = new
                    // ServerTilKlientPakke('A', 0, 0, 'W', "Martin", "Karl");
                    // broadcastObject(returPakke);

                    broadcast(message);
                    // broadcast(nyPakke.getAfsender());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            handlers.remove(this);
        }
        stop();
    }

    public synchronized void start() {
        if (listener == null) {
            try {

                dataOut = new ObjectOutputStream(new BufferedOutputStream(
                        socket.getOutputStream()));
                dataIn = new ObjectInputStream(new BufferedInputStream(socket
                        .getInputStream()));

                listener = new Thread(this);
                listener.start();
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
                System.out.println(socket.getRemoteSocketAddress());
            }
        }
    }

    public synchronized void stop() {
        if (listener != null) {
            try {
                if (listener != Thread.currentThread())
                    listener.interrupt();
                listener = null;
                dataOut.close();
                System.out.println(socket.getRemoteSocketAddress()
                        + " --- stop");
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
                System.out.println(socket.getRemoteSocketAddress());
            }
        }
    }

    protected synchronized void broadcast(String message) {
        synchronized (handlers) {
            int i = 0;
            while (i < handlers.size()) {
                SpillerHandler handler = (SpillerHandler) handlers.get(i);
                i++;
                try {
                    handler.dataOut.writeUTF(message);
                    handler.dataOut.flush();
                } catch (IOException ex) {
                    handler.stop();
                }
            }
        }
    }

    protected synchronized void broadcastObject(ServerTilKlientPakke pakke) {
        synchronized (handlers) {
            int i = 0;
            while (i < handlers.size()) {
                SpillerHandler handler = (SpillerHandler) handlers.get(i);
                i++;
                try {
                    handler.dataOut.writeObject(pakke);
                    handler.dataOut.flush();
                } catch (IOException ex) {
                    handler.stop();
                }
            }
        }
    }
}
Avatar billede montago Praktikant
24. september 2007 - 11:25 #1
din Server har jo kun 1 socket...

endten skal du lige en tur på google og lede efter "multithreaded client server"

man laver normalt en socket listener, som reagere på requests fra nye clienter, i dit mainloop opretter man en tråd med en dedikeret socket til hver klient -- evt laver man en threadpool hvis du skal kunne håndtere mange klienter (mere end 10)

når en klient laver et nyt socket-interrupt request bliver tråden endten oprettet eller lagt aktiv i threadpoolen som håndtere dataflowet...

der står garanteret noget i bogen til dit fag... ellers skal du kigge på http://java.sun.com/docs/books/tutorial/essential/concurrency/ og de andre artikler på siden.
Avatar billede arne_v Ekspert
24. september 2007 - 15:25 #2
montago>

implements Runnable

lyder ikke singlethreaded i mine oerer
Avatar billede arne_v Ekspert
24. september 2007 - 15:27 #3
gon>

Hvordan bruger du din PacketHandler klasse ?

Faar du kaldt start inden run ?

(jeg er absolut ikke glad for den konstruktion med Runnable + start + run, men ...)
Avatar billede arne_v Ekspert
24. september 2007 - 15:28 #4
Du kan ogsaa proeve at aabne input foer output da output aabner foer input paa server.
Avatar billede gon Nybegynder
24. september 2007 - 19:02 #5
Tak for input allesammen.
Selve strukturen er jeg heller ikke selv glad for, men det var det kode vi fik udleveret (kan være jeg begynder forfra hvis dette her ikke går). Som nævnt så er de nævnte klasser ikke selve main-trådene der kører.
Det mystiske er, at koden VIRKER såfremt der overføres strings vha. DataOutputStreams og inputstreams endda med flere klienter. Prøves samme kode med objectstreams virker det ikke, hvilket er årsagen til mit spørgsmål.

På serversiden ser main sådan ud:

-------------------------------------

import hvad der skal bruges.

public class StartServer{

public static void main (String args[] ) throws IOException{

ServerSocket server = new ServerSocket(2004);

  System.err.println("Server Ready");
 
try{

 
  while(true){
      clientSocket = sSocket.accept();
      System.out.println("Forbindelse fra " + clientSocket.getRemoteSocketAddress();
      //starter tråd nævnt i spørgsmål som "kode server"
      SpillerHandler handler = new SpillerHandler(client);
      handler.start();
}}} //afslut klammer.
Avatar billede arne_v Ekspert
24. september 2007 - 19:09 #6
Har du proevet:

server:
  ObjectOutputStream
  ObjectInputStream

client:
  ObjectInputStream
  ObjectOutputStream

?
Avatar billede gon Nybegynder
25. september 2007 - 09:33 #7
Det er desværre ikke et tilfælde af concurrency (vil jeg mene). Koden virker som sagt hvis der anvendes en DataOutputStream samt en DataInputStream og der sendes tråde. Skiftes der til en Object-Output/Input-Stream (som bør kunne sende Strings som objekter) virker koden ikke.

Jeg leder derfor efter årsagen til dette - der må være en principiel forskel i den måde ObjectStream kommunikerer på eller opretter dens streams der er årsaget.

@arne_v: tak for hjælpen, men jeg udforskede alle kombinationer inden jeg forsøgte mig her på eksperten :=) - nogle af dine svar i andre spørgsmål gjorde mig opmærksom på at det kunne være et problem.
Avatar billede arne_v Ekspert
26. september 2007 - 04:24 #8
Fordi Data*Stream ikke låser behøver det ikke at betyde at Object*Stream ikke låser.

Men hvis det er testet, så må der jo være noget andet.

Det er imidlertid ret svært at finde uden kode der kan køres.

Kan du copy paste det vi mangler for at kunne prøve at køre programmerne ?
Avatar billede gon Nybegynder
03. oktober 2007 - 22:22 #9
Vi har skiftet tilbage til dataoutputstreams og tingene kører fint nu - jeg ved ikke hvordan jeg afslutter spørgsmålet teknisk, men nu er det gjort i "ånd".
Avatar billede gon Nybegynder
28. januar 2008 - 20:11 #10
lukker
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