Avatar billede trp79 Nybegynder
22. december 2002 - 18:49 Der er 31 kommentarer og
1 løsning

Chat server - respons

Jeg har en chat server som ser således ud:

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

public class Server
{
    public static Socket array[] = new Socket[42];
    public static String user[] = new String[42];
    public static int i = 0;

    public static void main(String args[])
    {

        try
        {
            BinaertTrae bt = new BinaertTrae(); //oprettelse af nyt binaertTrae objekt

            System.out.println("Vent et øjeblik, programmet loader og indlæser bruger-database!");

            bt.hentDB(); //metode kald, der henter databasen frem i det binære træ bt.

            ServerSocket serversocket = new ServerSocket(8205);

            while(true)
            {
                System.out.println("Venter på klient...");

                Socket incoming = serversocket.accept();

                array[i] = incoming;
                i++;

                ultra_thread ut = new ultra_thread(incoming,bt,user);

                ut.start();
            }

        }
        catch (Exception exc) {
            System.out.println("Fejl ! "+ exc.toString());
        }
    }

}


class ultra_thread extends Thread
{
    Socket incoming;
    BinaertTrae    bt;
    int a=0;

    ultra_thread (Socket pincoming, BinaertTrae b, String[] user) {
        incoming = pincoming;
        bt = b;
    }

    public void run() {
        try
        {

            BufferedReader in = new BufferedReader
            (new InputStreamReader(incoming.getInputStream()));

            String string;

        //    String Brugernavn= in.readLine();;
        //    String Password= in.readLine();;
            String rettighed=/*bt.soeg(Brugernavn,Password);*/"1";
            System.out.println(rettighed);

            if(Integer.parseInt(rettighed)==1 || Integer.parseInt(rettighed)==2)
            {
        //        System.out.println(Brugernavn+" signed in. Userlevel: "+rettighed);

                    while(true)
                    {

                        string = in.readLine();

                        if(string.compareTo("/exit")==0)
                            break;
                        if(string.compareTo("/user")==0)
                            userlist(Integer.parseInt(rettighed));

                        if(string.compareTo("/killserver")==0)
                        {
                            bt.gemDB();
                            System.out.println("Programmet gemmer og lukker.");
                            try
                                {
                                    Thread.sleep(1000);
                                }
                            catch(InterruptedException q)
                                {}
                            System.exit(0);
                        }

                        System.out.println(string);

                        for(int taeller = 0;taeller < Server.i;taeller++)
                        {
                            PrintStream out = new PrintStream(Server.array[taeller].getOutputStream());
                            out.println(string);
                        }
                    }
            }

            incoming.close();
        }
        catch (Exception exc) {
            System.out.println("Fejl ! "+ exc.toString());
        }


    }

    public void user(String Puser)
    {
    String user= Puser;
//    user[a]= user;
//    a++;
    }

    public void userlist(int rettighed)
    {
        if(rettighed==1)
        {
            //Udskriv tabel med brugere...
        }

        else
        System.out.println("Du har ikke rettighed til at se brugerliste.");
    }

}

Den indlæser altså indholdet(fx. brugernavn, password) af en database i et binært træ.
Er det muligt på en måde at sende en besked fra serveren til EN BESTEMT klient? (fx til tjek på brugernavn/password)eller er man nød til at sende ud til alle klienterne?)
Er det desuden muligt at trække andre oplysninger ud af serveren omkring de enkelte klienter, som fx ip?

Hvis noget af overstående er muligt vil jeg gerne have en forklaring på hvordan det kan gøres.
Mvh
Torben
Avatar billede dsj Nybegynder
22. december 2002 - 19:15 #1
Som jeg kan forstå på det har du forbindelserne til dine klienter i array[]. På dine connections kan du selvfølgelig finde ip og port på hver enkelt klient. Hvis nu du laver array om til array[x][3], så kan du i array[x][0] gemme selve forbindelsen, i array[x][1] kan du gemme brugernavn og i array[x][2] gemme password. på denne måde har du de rigtige brugernavne og adgangskoder på hver enkelt klient. Så kan du løbe array igennem, finde forbindelsen med det korrekte brugernavn og kun sende beskeden til denne.
Avatar billede arne_v Ekspert
22. december 2002 - 19:16 #2
Ja. Du skal bare gemme sockets og så finde den socket der
passer til et brugernavn.
Avatar billede arne_v Ekspert
22. december 2002 - 19:17 #3
Erstat:
  Socket incoming = serversocket.accept();
med:
  array[i] = serversocket.accept();

og når du skal bruge en socket for en bestemt bruger så
løber du gennem user arrayet og finder brugeren og så er
socketen i samme position i det array som hedder array.
Avatar billede arne_v Ekspert
22. december 2002 - 19:19 #4
private Socket findsocket(String usr) {
    for(int i = 0; i < user.length; i++) {
        if(user[i].equals(usr)) {
            return array[i];
        }
    }
    return null;
}
Avatar billede arne_v Ekspert
22. december 2002 - 19:22 #5
Ignorer midt midterste svar. Du gemmer allerede incoming i array.

Fu mangler nok snarere at få akitiveret koden i:

public void user(String Puser)
    {
    String user= Puser;
//    user[a]= user;
//    a++;
    }

måske:

public void user(String Puser)
    {
    String user= Puser;
    user[i-1]= user;  // i-1 fordi i blev talt op da socketen blev lagt ind
    }
Avatar billede arne_v Ekspert
22. december 2002 - 19:24 #6
Eller måske skal du helt droppe den funktion og bare sætte
den relevante linie ind i run metoden.
Avatar billede arne_v Ekspert
22. december 2002 - 19:25 #7
Der er mange måder at lave det på.

Det vigtigste er at du får de to arrays user og array (du bør finde
et andet navn til det !) opdateret så værdierne matcher, så kan du
altid finde socket for en bruger.
Avatar billede dsj Nybegynder
22. december 2002 - 19:27 #8
Nu skriver han jo allerede:

Socket incoming = serversocket.accept();
array[i] = incoming;

;)
Avatar billede arne_v Ekspert
22. december 2002 - 19:28 #9
Jep. Det opdagede jeg også.
Avatar billede arne_v Ekspert
22. december 2002 - 19:41 #10
Til gengæld er jeg ikke overbevist om visdommen i at 2 dimensionelt
array of type Object til at gemme sockets og brugernavne (+pasword) i !
Avatar billede dsj Nybegynder
22. december 2002 - 20:06 #11
nej, det var kun en meget nem tilgang til det...
Avatar billede trp79 Nybegynder
22. december 2002 - 22:58 #12
Skønt at se så mange og forklarende indlæg :o) Men hvordan trækker jeg diverse oplysninger omkring den enkelte klient ud af serveren (kodemæssigt)?
Avatar billede arne_v Ekspert
22. december 2002 - 23:03 #13
Hvis du skal finde socket udfra username for at kunne sende til
en bestemt bruger, så skal du:
  - sørge for at de to arrays med sockets og usernames matcher
  - bruge min kode fra 19:19:36 til at find esocketen
Avatar billede trp79 Nybegynder
22. december 2002 - 23:04 #14
Det jeg mener er at hvis man gør det sådan her:

array[i] = incoming;
i++;
System.out.println(array[i-1]);

Så får man alle informationer ud.... kan man på nogen måde nøjes med at trække ipen ud eller kan man på nogen måde gennemsøge et Socket array, som fx hvis det var strenge?
Avatar billede arne_v Ekspert
22. december 2002 - 23:07 #15
Hvis du vil gemme flere oplysninger, så bør du lave en klasse
som indeholder alle oplysninger og lave et array af den.

public class UserInfo {
  private Socket socket;
  private String user;
  private String otherinfo;
  public class UserInfo(Socket socket, String user, String otherinfo) {
      this.socket = socket;
      this.user = user;
      this.otherinfo = otherinfo;
  }
  public getSocket() {
      return socket;
  }
  public getUser() {
      return user;
  }
}
Avatar billede arne_v Ekspert
22. december 2002 - 23:11 #16
Du vil gå fra socket til user ?

Du kan godt søge med:

private String finduser(String sock) {
    for(int i = 0; i < array.length; i++) {
        if(array[i].equals(sock)) {
            return user[i];
        }
    }
    return null;
}
Avatar billede arne_v Ekspert
22. december 2002 - 23:11 #17
Hvilket stadig forudsætter at de to arrays user og array matcher
hinanden.
Avatar billede trp79 Nybegynder
22. december 2002 - 23:15 #18
Ok, det lyder godt! Men hvordan sørger jeg for at hvis jeg kun skriver til fx klienten hvis info ligger gemt i array[1]?

Den første kommentar der er skrevet forstår jeg således at hvem gang en klient connecter så skal samtlige brugernavne og passwords sendes dertil. Er det ikke lidt uhensigtsmæssigt?
Avatar billede arne_v Ekspert
22. december 2002 - 23:19 #19
????

Ingen klienter snakker direkte med hinanden. Alle klienter snakker
kun med server.

Bruger A skriver ind på den socket der er gemt i array[7] og angiver
at bruger Z skal have beskeden.

Serveren bruger brugernavn Z til at finde ud af at det user[9]
of bruger så socket[9] til at sende besked ud til bruger Z.

Brugernavn/password valideres af serveren, når de signer på, men
sendes aldrig ud til andre klienter.
Avatar billede arne_v Ekspert
22. december 2002 - 23:21 #20
Hvis jeg skulle brodere lidt videre på UserInfo klassen:

import java,util.*;

public class Clients {
  private ArrayList list;
  public Clients() {
      list = new ArrayList();
  }
  public void add(Socket socket, String user, String otherinfo) {
      list.add(new UserInfo(socket, user, otherinfo));
  }
  public Socket findSocketByUser(String user) {
      for(int i = 0; i < list.size(); i++) {
        if(((UserInfo)list.get(i)).getUser().equals(user)) {
            return ((UserInfo)list.get(i)).getSocket();
        }
    }
    return null;
  }
  public String findUserBySocket(Socket sock) {
      for(int i = 0; i < list.size(); i++) {
        if(((UserInfo)list.get(i)).getSocket().equals(sock)) {
            return ((UserInfo)list.get(i)).getUser();
        }
    }
    return null;
  }
}

Så kan du også håndtere et variabel antal klienter !
Avatar billede trp79 Nybegynder
22. december 2002 - 23:29 #21
Det jeg tænker på er det, som står i det allerførste(19:15:22) svar "på denne måde har du de rigtige brugernavne og adgangskoder på hver enkelt klient". Hvis det nu var dig der skulle lave en simpel validering, hvordan vil du så gøre det på klient siden? Jeg har lavet en metode, som gennemsøger det binæretræ og returnerer true, hvis det er det rigtige brugernavn/password.

Tilbage til det andet problem....
Hvordan sender jeg en besked til den bruger der er på fx. socket[9] ?
Avatar billede trp79 Nybegynder
22. december 2002 - 23:32 #22
De er jo forrygende de kode-eksempler du kommer med!!
Avatar billede arne_v Ekspert
22. december 2002 - 23:35 #23
Indlægget 19:15:22 er ikke fra mig men fra dsj.

Jeg er sikke rpå at han mener "for" hver klient ikke "på" hver
klient.

Jeg ville absolut lave validereingen pås erver side. Det er både
nemmest at kode og mest sikker.

Dit binære træ lyder som en udmærket løsning.

Det er nemt at sendt til en socket.

Du kan hente en output stream med getOutputStream og
write'e til den eller måske endnu bedre create en ObjectOutputStream
udfra den, så ddu kan sende Java objects istedetfor byte arrays.
Avatar billede trp79 Nybegynder
22. december 2002 - 23:50 #24
Det sidste du siger er jeg ikke helt med på :o( Jeg er helt ny på det hersens netværksområde... hvordan fungerer getOutputStream? (jeg går ud fra at det er den metode jeg skal bruge til at skrive til en bestemt socket....
Avatar billede arne_v Ekspert
23. december 2002 - 07:38 #25
Socket s;
MyObject o;

ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream);
oos.writeObject(o);
Avatar billede arne_v Ekspert
23. december 2002 - 07:39 #26
Ham i den andeb ender brufer så getInputStream, ObjectInputStream
of readObject til at læse med.
Avatar billede trp79 Nybegynder
23. december 2002 - 11:19 #27
Ved ikke om det er mig der er helt blank, men når jeg forsøger mig med ObjectOutputStream får jeg en fejl på getOutputStream:

cannot resolve symbol
symbol  : variable getOutputStream 
location: class java.net.Socket
                ObjectOutputStream oos = new ObjectOutputStream(array[i-1].getOutputStream);

getOutputStream er vel en metode, så jeg fatter ikke helt fejlen.
Jeg vil blot prøve at sende et object for at teste det:

while(true)
            {
                System.out.println("Venter på klient...");

                Socket incoming = serversocket.accept();

                array[i] = incoming;
                i++;
                ObjectOutputStream oos = new ObjectOutputStream(array[i-1].getOutputStream);
                user("Brugernavn");
                System.out.println(array[i-1]);

                ultra_thread ut = new ultra_thread(incoming,bt,user);

                ut.start();
            }
Avatar billede arne_v Ekspert
23. december 2002 - 11:59 #28
Min fejl.

Prøv lige med:
ObjectOutputStream oos = new ObjectOutputStream(array[i-1].getOutputStream());

[paranteser tilføjet for at markere at det er et metode-kald]
Avatar billede trp79 Nybegynder
23. december 2002 - 17:56 #29
Ups... okey den burde jeg nok også have luret... Men jeg takker mange gange, nu virker det jo forrygende :o)
God jul :o)
Avatar billede trp79 Nybegynder
24. december 2002 - 12:17 #31
Nope har ikke set den side før :o( Men den ser da ud til at kunne være til stor nytte :o) Jeg takker!
Avatar billede arne_v Ekspert
24. december 2002 - 14:04 #32
Det er jo altid sjovere selv at lave tingene. Men man kan jo altid
lære lidt af andres løsninger. Og IBM har rigtigt gode Java folk.
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