Avatar billede aggemamme Nybegynder
10. februar 2003 - 02:58 Der er 40 kommentarer og
1 løsning

Kø-system

Hej

Jeg er ved at lave en serverapplikation, der tager imod tekst fra en klient og herefter lægger dette i en kø til at blive afsendt som SMS.

Jeg tager udgangspunkt i eksemplerne fra denne tutorial:
http://java.sun.com/docs/books/tutorial/networking/sockets/clientServer.html

Og jeg er kommet så langt som at tage imod data fra klienter og gemme i variabler.

Da jeg ikke har megen erfaring med Java, er jeg stødt ind i et problem i forbindelse med at lave en kø. Jeg har lavet en ny class, SMSServerQueue, som oprettes en enkelt gang når serveren starter (der skal jo kun være een kø).

Ligesom i eksempel på tutorialen har jeg andre klasser, SMSServerThread og SMSServerProtocol. Hvordan kan jeg tilgænge metoderne i den samme "instans" af SMSServerQueue inde fra fx SMSServerProtocol? Fx hvis en SMS skal lægges i køen.

Jeg håber, at det er forklaret, så det forstås. Jeg er ikke helt inde i terminologien der gælder for objekt-orienteret programmering.
Avatar billede jakoba Nybegynder
10. februar 2003 - 03:15 #1
siden der kun skal være een eneste kø kan du lade variable og metoder i din klasse SMSServerQueue være statiske. så kan de tilgås allevegnefra med klassenavnet foran det lokale navn i klassen.
eg:

class SMSServerQueue {
    private static Koelement[] koen = new Koelement[100];  // bare et eksempel
    private static int forste = 0;
    private static int sidste = 0;  // forste==sidste => tom kø

    public static tilfoj( Koelement sms ) {
        if ( (sidste+1)%100 != forste ) {
            koen[sidste] = sms;
            sidste = (sidste+1)%100;
        } else {
            // grumme fejl. det må ikke ske
        }
    }
    public static hentNeste( ) {
        if ( forste == sidste ) {
            // koen er tom.
            return null;
        } else {
            int temp = forste;
            forste = (forste+1)%100;
            return koen[temp];
        }
    }

}

fra andre klasser kan du nu kalde
    SMSServerQueue.tilfoj( element );
og
    element = SMSServerQueue.hentNeste();
    if ( element != null ) {
        // send den sms
    }

mvh JakobA
Avatar billede jakoba Nybegynder
10. februar 2003 - 03:18 #2
ups. metoder skal have en type de kan returnere (eller void)
    public static void tilfoj( Koelement sms ) {  // returnere ingenting
    public static Koelement hentNeste( ) {        // returnerer et Koelement (eller null)
Avatar billede jakoba Nybegynder
10. februar 2003 - 03:22 #3
Ps: du behøver ikke oprette en instans af SMSServerQueue.  De statiske variable får allokeret plads blot du refererer til den klasse.
Avatar billede aggemamme Nybegynder
10. februar 2003 - 03:30 #4
Hej og tak for svaret!

Jeg prøver lige at flikke noget sammen - jeg regner dog nok med at bruge en Vector til at opbevare elementerne i køen i.
Avatar billede aggemamme Nybegynder
10. februar 2003 - 03:45 #5
Informationerne, der skal opbevares i køen, er: "Type", "Modtager" og "Data". Hvordan opbevares dette mest optimalt? Det er alle tekststrenge.

Ville tre vector'er være en god løsning?
Avatar billede arne_v Ekspert
10. februar 2003 - 06:33 #6
Mit forslag:

import java.util.*;

public class Queue {
    private LinkedList q = null;
    public Queue() {
        q = new LinkedList();
    }
    public void enq(Object o) {
        q.addLast(o);
    }
    public Object deq() {
        return q.removeFirst();
    }
}

public class SMS {
    private String type;
    private String modtager;
    private String data;
    public String getData() {
        return data;
    }
    public String getModtager() {
        return modtager;
    }
    public String getType() {
        return type;
    }
    public void setData(String data) {
        this.data = data;
    }
    public void setModtager(String modtager) {
        this.modtager = modtager;
    }
    public void setType(String type) {
        this.type = type;
    }

}

Queue serverQueue = new Queue();
serverQueue.enc("a", "b", "c");
SMS x = (SMS)serverQueue.deq();
Avatar billede arne_v Ekspert
10. februar 2003 - 06:35 #7
Hvis du kun skal have en enkelt kø som skal accesses fra
flere klasser, så kan du enten lave en singleton wrapper
eller (i dette tilfælde) bare erklære den public static.
Avatar billede soelvpil Nybegynder
10. februar 2003 - 08:34 #8
arne_v's er helt klart den ide du bør bruge.

Saml dine data i et objekt, det er meget bedre end 3 vektorer.

Der er lige den lille detalje, at den ikke kan kompilere. Jeg vil foreslå at rette SMS-klassen, så den ikke har set-metoder, men i stedet har en constructor der tager 3 argumenter.
Avatar billede arne_v Ekspert
10. februar 2003 - 08:45 #9
Du må referere til:

serverQueue.enc("a", "b", "c");

Som selvfølgelig er noget sludder.

Det skal enten være:

SMS z = new SMS();
z.setData("a");
z.setModtager("b");
z.setType("c");
serverQueue.enc(z);

Eller som du foreslår:

serverQueue.enc(new SMS("a", "b", "c"));

med:

public class SMS {
    private String type;
    private String modtager;
    private String data;
    public SMS(String type, String modtager, String data) {
        this.data = data;
        this.modtager = modtager;
        this.type = type;
    }
    public String getData() {
        return data;
    }
    public String getModtager() {
        return modtager;
    }
    public String getType() {
        return type;
    }
    public void setData(String data) {
        this.data = data;
    }
    public void setModtager(String modtager) {
        this.modtager = modtager;
    }
    public void setType(String type) {
        this.type = type;
    }

}
Avatar billede arne_v Ekspert
20. februar 2003 - 18:14 #10
am>

Har du fået løst dit problem ?
Avatar billede aggemamme Nybegynder
06. marts 2003 - 00:08 #11
Hej,

Beklager at jeg ikke har svaret før nu! Jeg opdagede pludselig en bølge af diverse andre ting at lave :-)

Jeg regner med at genoptage projektet i næste uge. Men den information, I her har givet, ser meget lovende ud!

Jeg vender frygteligt tilbage, ok?
Avatar billede aggemamme Nybegynder
13. marts 2003 - 19:58 #12
Så er jeg på banen igen :-)

Jeg har forsøgt at implementere arne_v's ide, og får følgende fejl ved kompilering:

SMSServerProtocol.java:69: Can't make static reference to method void enq(java.lang.Object) in class SMSServerQueue.
                SMSServerQueue.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));
                                  ^
SMSServerQueue.java:5: Class LinkedList not found in type declaration.
  private LinkedList q = null;
                      ^
SMSServerQueue.java:8: Class LinkedList not found in type declaration.
    q = new LinkedList ();

Det er sikkert bare mig, der som sagt er ny i Java - men I siger selv til, når I mener, at I har udført for 60 points hjælp, ok? :-)
Avatar billede arne_v Ekspert
13. marts 2003 - 20:05 #13
LinkedList not found

lyder som om:

import java.util.*;

mangler !
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:07 #14
Det tænkte jeg også, men den står på sin plads i filen med klassen SMSServerQueue, hvor LinkedList bruges ... Er LinkedList afhængigt af en bestemt version af JDK?
Avatar billede arne_v Ekspert
13. marts 2003 - 20:09 #15
Den første fejl-besked lyder som om du skal erstatte:

SMSServerQueue.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));

med:

SMSServerQueue ssq = new SMSServerQueue();
ssq.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));

men du skal nok lige checke om det passer med din kode logik.
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:09 #16
Jeg bruger JDK(tm) 1.1.8 til FreeBSD.
Avatar billede arne_v Ekspert
13. marts 2003 - 20:10 #17
LinkedList blev tilføjet i version 1.2 (og den er efterhånden ret gammel !).

Kan du poste hele SMSServerQueue.java ?
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:11 #18
>SMSServerQueue ssq = new SMSServerQueue();

Skal denne kun ikke udføres en enkelt gang, fx når SMS-serveren starter? Sådan at der kun oprettes een kø?
Avatar billede arne_v Ekspert
13. marts 2003 - 20:12 #19
Ups. Ja så mangler den.

Kan du ikke få noget nyere end 1.1.8 til FreeBSD ?
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:12 #20
OK, så skal jeg vist opgradere :-)

Jeg poster lige hele SMSServerQueue.java:

import java.util.*;

public class SMSServerQueue {

  private LinkedList q = null;

  public SMSServerQueue() {
    q = new LinkedList ();
  }

  public void enq(Object o) {
    q.addLast(o);
  }

  public Object deq() {
    return q.removeFirst();
  }

}
Avatar billede arne_v Ekspert
13. marts 2003 - 20:15 #21
Nå skidt pyt.

Vi skifter vel bare til Vector:

import java.util.*;

public class Queue {
    private Vector q = null;
    public Queue() {
        q = new LinkedList();
    }
    public void enq(Object o) {
        q.add(o);
    }
    public Object deq() {
        Object o = q.get(0);
        q.removeElementAt(0);
        return o;
    }
}

[tastet ind her uden at være testet]
Avatar billede arne_v Ekspert
13. marts 2003 - 20:15 #22
Vector har været i JDK siden version 1.0 !
Avatar billede arne_v Ekspert
13. marts 2003 - 20:16 #23
Så du behøver ikke opdatere bare for at løse dette problem.

Men generelt tror jeg at det ville være en god ide at opdatere.
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:18 #24
OK, kan jeg så stadig bruge

serverQueue.enc(new SMS("a", "b", "c"));

til at lægge ting ind i køen?

Skal det så ikke være

  public Queue() {
        q = new Vector();
    }

også her, i stedet for LinkedList?
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:25 #25
Nu er den eneste fejl ved kompilering den samme som tidligere nævnt:

SMSServerProtocol.java:69: Can't make static reference to method void enq(java.lang.Object) in class SMSServerQueue.
                SMSServerQueue.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));
Avatar billede arne_v Ekspert
13. marts 2003 - 20:28 #26
Ups.

Ja selvfølgelig skal det også være new Vector:

import java.util.*;

public class Queue {
    private Vector q = null;
    public Queue() {
        q = new Vector();
    }
    public void enq(Object o) {
        q.add(o);
    }
    public Object deq() {
        Object o = q.get(0);
        q.removeElementAt(0);
        return o;
    }
}

Og ja den kan bruges helt ligesom den anden.
Avatar billede arne_v Ekspert
13. marts 2003 - 20:30 #27
Og det er den som jeg mener skal løses med:

SMSServerQueue ssq = new SMSServerQueue();
ssq.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));


og ja den første linie skal kun udføres en gang.

Så erklæringen:
  SMSServerQueue ssq;
skal nok ligge et rimeligt centralt sted.

Og så skal:
  ssq = new SMSServerQueue();
ligge i en constructor eller noget andet initialiserings kode.
Avatar billede arne_v Ekspert
13. marts 2003 - 20:32 #28
Alternativt skal du køre rent static altså:

import java.util.*;

public class Queue {
    private static Vector q = new Vector();
    public static void enq(Object o) {
        q.add(o);
    }
    public static Object deq() {
        Object o = q.get(0);
        q.removeElementAt(0);
        return o;
    }
}
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:32 #29
Jeg har også rettet den til, så der står

q.addElement(o);

i stedet for q.add(o);

og

q.elementAt(0);

i stedet for q.get(0)

Men fejlen som jeg har pastet tidligere vil ikke forsvinde :)
Avatar billede arne_v Ekspert
13. marts 2003 - 20:32 #30
Men generelt betragtes det ikke som værende kønt med så meget static.
Avatar billede arne_v Ekspert
13. marts 2003 - 20:34 #31
Ja ups.

Ganske vist er Vector fra 1.0, men add og get blev først tilføjet i 1.2 - sorry !

Med hensyn til fejlen så se nogle af mine sidste kommentarer.
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:36 #32
Jep, jeg kigger lige på det :)
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:46 #33
Så har jeg rettet lidt til.

I klassen SMSServerProtocol, hvor SMSen lægges i køen fra, står nu "SMSServerQueue ssq;".
I klassen SMSServer, der afvikles som det første, står nu "SMSServerQueue ssq = new SMSServerQueue;"

Der er ingen fejlmeddelelser ved kompilering længere.

Når jeg prøver at lægge en SMS i køen ved at telnette til serveren, skriver den "Invalid data", dvs den har catchet noget ...

              try {
                ssq.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));
                theOutput = "OK. Your SMS will be processed.";
                state = FINISHED;
              } catch (Exception err) {
                theOutput = "Invalid data.";
                state = WAITING_DATA;
              }
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:48 #34
1000 millioner tak for hjælpen indtil nu ! Jeg løber lige over efter noget mad :-)
Er snart tilbage...
Avatar billede arne_v Ekspert
13. marts 2003 - 20:49 #35
Prøv med:

              try {
                ssq.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));
                theOutput = "OK. Your SMS will be processed.";
                state = FINISHED;
              } catch (Exception err) {
                err.printStackTrace();
                theOutput = "Invalid data.";
                state = WAITING_DATA;
              }
Avatar billede aggemamme Nybegynder
13. marts 2003 - 20:53 #36
java.lang.NullPointerException
        at SMSServerProtocol.processInput(SMSServerProtocol.java:72)
        at SMSServerThread.run(SMSServerThread.java:26)

På linie 26 i ...Thread.java står :

                outputLine = protocol.processInput(inputLine);

På linie 72 i ... Protocol.java står:

                ssq.enq(new SMSServerSMS(theInput, entered_receiver, entered_type));
Avatar billede arne_v Ekspert
13. marts 2003 - 21:06 #37
Umiddelbart lyder det som ssq er null fordi den ikke er blever initialiseret.
Avatar billede arne_v Ekspert
13. marts 2003 - 21:09 #38
Hov !

#I klassen SMSServerProtocol, hvor SMSen lægges i køen fra, står nu "SMSServerQueue ssq;".
#I klassen SMSServer, der afvikles som det første, står nu "SMSServerQueue ssq = new SMSServerQueue;"

Det skal være SMSServerProtocol.java:
  public static SMSServerQueue ssq;

og SMSServer.java:
  SMSServerQueue.ssq = new SMSServerQueue();

eller noget tilsvarende !
Avatar billede aggemamme Nybegynder
13. marts 2003 - 21:16 #39
SMSServerQueue.ssq = new SMSServerQueue();

Skal der punktum imellem de to?
Avatar billede arne_v Ekspert
13. marts 2003 - 21:21 #40
Ja.

Men det skal være:

  SMSServerProtocol.ssq = new SMSServerQueue();

"sæt ssq variablen i klassen SMSServerProtokol"
Avatar billede aggemamme Nybegynder
13. marts 2003 - 21:24 #41
Lækkert - nu kører det ... :-)

Nu skal jeg så bare lave den del, der læser køen og sender SMS ud - men det vil jeg selv prøve :-)

Da det var din (arne_v's) ide jeg bruger, håber jeg at jeg er retfærdig nok ved at give de 60 point til dig ...
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