Avatar billede langkiller Nybegynder
07. april 2013 - 16:43 Der er 35 kommentarer og
1 løsning

timeout på readline hvis der ikke kommer noget input

prøver at finde ud af hvordan jeg kan sætte en timeout på min readline. Grunden til jeg vil det, er at jeg gerne vil have programmet til at gå videre hvis readline ikke får nogen værdi fra client. en slags timeout.. eller anden løsning hvis det er bedre. Har følgende kode hvor jeg gerne vil have den til at tjekke readline om den har en værdi og derefter gå videre:

int i = 0;
                        while (i < clientBuffReader.size()) {
                            BufferedReader inFromClient = (BufferedReader) clientBuffReader.get(i);
                           
                            oText = inFromClient.readLine();
                               
                            if (!oText.equals(null)) {

                                int a = 0;
                                while (a < clientPrintWriter.size()) {
                                    Socket writeToServerSocket = (Socket) clientSockets.get(a);
                                    PrintWriter writeToClient  = (PrintWriter) clientPrintWriter.get(a);
                                    writeToClient.println(oText);
                                    a++;
                                }
                                messageField.append(oText);
                               
                            }
                                                   
                            i++;
                        }
Avatar billede arne_v Ekspert
07. april 2013 - 17:13 #1
Jeg tror at du skal skifte til GUI.

Avancerede funktioner i Java console IO er meget tricky at faa til at virke korrekt.
Avatar billede langkiller Nybegynder
07. april 2013 - 17:27 #2
jamen jeg har skam en GUI.. har bare delt gui og logik op så det er en gui der modtager teksten fra printwriter
Avatar billede langkiller Nybegynder
07. april 2013 - 17:33 #3
ved ikke hvordan jeg skal løse problemet.. men det der er galt er at når man fx. har 2 clients og skriver fra dem, så skal de skiftes til at få vist deres besked i textarea.. og tror det skyldes at readline blokerer på en eller anden måde.
Avatar billede arne_v Ekspert
07. april 2013 - 23:04 #4
Hvis du allerede har en GUI saa forstaar jeg ikke hvorfor du bakser med readLine?
Avatar billede langkiller Nybegynder
08. april 2013 - 00:02 #5
Hvad ville du så foreslå at jeg bruger ? Har dog fået det til vat køre nu, ved bare ikke om det er optimalt.

Har et andet spørgsmål som jeg tænkte jeg ligeså godt kunne stille her. Prøver at sende nogle Arraylists fra server til client, som bl.a. indeholder buffered reader, men kan ikke få det til at virke. Har prøvet at bruge ObjectOutputStream, men tror ikke jeg gør det korrekt.


                        ArrayList<BufferedReader> clientBuffReader = serverReg.getBRArray();

                            ObjectOutputStream out = new ObjectOutputStream(clientSock.getOutputStream());


                            out.writeObject(clientBuffReader);



Prøver så at modtage den (og sætte det) på client med dette:

ois = new ObjectInputStream(clientSocket.getInputStream());
clientReg.setBRArray((ArrayList<BufferedReader>) ois.readObject());
Avatar billede langkiller Nybegynder
08. april 2013 - 00:04 #6
Har bl.a. fået denne fejl:

java.io.StreamCorruptedException: invalid stream header: 78785365
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at chatClient.ChatClientHandler$GetMessages.run(ChatClientHandler.java:88)


linje 88 er:                 ois = new ObjectInputStream(clientSocket.getInputStream());

og en masse underlige udskrifter i mit textarea i min gui, bl.a. en masse tegn der ikke kan vises .
Avatar billede arne_v Ekspert
08. april 2013 - 02:51 #7
Du kan ikke sende en BufferedReader over en socket!
Avatar billede langkiller Nybegynder
08. april 2013 - 09:28 #8
okay det har jeg så også ændret nu. Sender bare en ArrayList<String> nu.
Har et sidste spørgsmål. Hvis jeg fra min server side, sender noget til client, kan det være forskellige slags data. I stedet for at jeg igennem en enkelt tråd på client siden, skal afgøre hvilken slags data det er, kan jeg så vælge hvilken tråd (hos client) der skal tage sig af det output fra server? Det er fordi min Buffered Reader hos client prøver at tage imod input, lige meget om det er ren tekst eller en ArrayList der bliver sendt. Ved ikke om jeg har forklaret mig ordenligt, men håber du forstår hvad jeg mener.
Avatar billede langkiller Nybegynder
08. april 2013 - 09:49 #9
jeg vil altså gerne bestemme hvilken tråd på modtager(client) siden der skal tage sig af outputtet fra serveren.
Avatar billede arne_v Ekspert
09. april 2013 - 01:59 #10
Hvis du har 2 forskellige slags data, saa ville jeg overveje:
- 2 sockets mellem client og server
- en traad for hver af de 2 sockets paa client
Avatar billede langkiller Nybegynder
09. april 2013 - 21:20 #11
valgte at løse mit problem på en anden måde. Har valgt at benytte mig af ObjectInputStream (og Output), men har et lille problem med det.. Vil gerne tjekke om der er noget at læse for readObject() og hvis der ikke er, gå videre i programmet.. ellers hænger den bare der og venter indtil der er input fra client.

Kan man tjekke det på en eller anden måde og så gå videre?
Avatar billede langkiller Nybegynder
09. april 2013 - 21:20 #12
Altså tjekke om der er noget at læse fra ObjectInputStream eller readObject?
Avatar billede arne_v Ekspert
09. april 2013 - 22:05 #13
Den nemme maade at kode paa er at laese og blokere indtil der er noget at laese. Det kraveer saa brug af traade.

Du kan lave ikke-blokerende IO ved at skifte fra java.io til java.nio, men det er generelt lidt mere vanskelige API'er.
Avatar billede arne_v Ekspert
09. april 2013 - 22:06 #14
Object*Stream er beregnet til hvor man vil skrive/laese komplekse java objekter.
Avatar billede langkiller Nybegynder
09. april 2013 - 22:15 #15
Okay, jeg må nok hellere droppe den løsning så. Det lyder som om ObjectStream er lidt overkill. Synes ellers det virkede som en fornuftig måde at gøre det på. Men hvis jeg ikke kan tjekke om der er noget at læse ved readObject() kan mit program ikke køre som det skal, så ender det med at klienterne skal skiftes om at skrive en besked til server
Avatar billede arne_v Ekspert
10. april 2013 - 01:04 #16
Det er vel et design problem!?
Avatar billede langkiller Nybegynder
10. april 2013 - 01:09 #17
ja det har du ret i. Har skifter min objectstream ud.
hmm hvordan ville du tjekke en readLine (buffered reader) om der er noget at læse (eller tjekke buffered reader... men uden at læse readline. Vil bare gerne tjekke om der er noget input
Avatar billede langkiller Nybegynder
10. april 2013 - 01:17 #18
har skrevet sådan her hvor der kigges efter nye beskeder og derefter skriver den til samtlige clients. Men sådan som det er nu, skal clients skiftes til at få sendt deres besked fordi readline venter på den næste input. Kan man ikke bare få den til at gå videre hvis der ikke er noget input? Eller gøre noget andet smart?


ArrayList<String> clientArray = serverReg.getClientArray();
                    ArrayList<PrintWriter> clientPWArray = serverReg.getClientPWArray();
                    ArrayList<BufferedReader> clientBRArray = serverReg.getClientBRArray();

                    int i = 0;
                    while(i < clientBRArray.size()) {

                        try {
                            inFromClient = clientBRArray.get(i);
                           
                                // ALMINDELIG TEKST BESKED
                                    if (checkMesType.getMesType(inputMes = inFromClient.readLine()) == 1 && inputMes != null) {
                                        messageField.append(checkMesType.getMes(inputMes));
                                       
                                        // Besked skrives til alle clients
                                            int p = 0;
                                            while (p < clientPWArray.size()) {
                                                outToClient = clientPWArray.get(p);
                                                outToClient.println("1." + checkMesType.getMes(inputMes));
                                                p++;
                                            }
                                       
                                    } else {
                                        System.out.println("bummmm");
                                    }
                           
                           
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                       
                        i++;
                    }
Avatar billede arne_v Ekspert
10. april 2013 - 02:56 #19
saa vidt jeg kan se er problemet at du ikke har en traad per klient
Avatar billede langkiller Nybegynder
10. april 2013 - 09:39 #20
det er jeg da ret sikker på jeg har.. har da denne tråd til modtagelse af nye klienter der koerer for sig selv :


   
   
    class GetNewUsers extends Thread
    {
        private BufferedReader inFromClient;
        private PrintWriter outToClient;
        private String navn, alder , clientToList;
       
        public void run()
        {
           
                while(serverReg.getServerconnection() == true) {
                   
                        try {
                            System.out.println("venter på forbindelse");
                            Socket connectionSocket    = serverSocket.accept();
                            System.out.println("Fik forbindelse!");
                           
                            outToClient = new PrintWriter(connectionSocket.getOutputStream(), true);
                            inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));

                            serverReg.setClientPWArray(outToClient);
                            serverReg.setClientBRArray(inFromClient);
                           
                            if (checkMesType.getMesType(navn = inFromClient.readLine()) == 0) {
                                if (checkMesType.getMesType(alder = inFromClient.readLine()) == 0) {
                                    clientToList = navn + "("+alder+")";
                                    serverReg.setClientArray(clientToList);
                                }
                            }
                           
                           
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                       
                }
               
               
        }
       
    }
Avatar billede langkiller Nybegynder
10. april 2013 - 09:41 #21
og denn tråd til at modtage input fra klienter:

   
   

    class GetInput extends Thread
    {
        PrintWriter outToClient;
        BufferedReader inFromClient;
        String inputMes;
       
        public void run()
        {
                while(serverReg.getServerconnection() == true) {

                    ArrayList<String> clientArray = serverReg.getClientArray();
                    ArrayList<PrintWriter> clientPWArray = serverReg.getClientPWArray();
                    ArrayList<BufferedReader> clientBRArray = serverReg.getClientBRArray();

                    int i = 0;
                    while(i < clientBRArray.size()) {

                        try {
                            inFromClient = clientBRArray.get(i);
                           
                                // ALMINDELIG TEKST BESKED
                                    if (checkMesType.getMesType(inputMes = inFromClient.readLine()) == 1 && inputMes != null) {
                                        messageField.append(checkMesType.getMes(inputMes));
                                       
                                        // Besked skrives til alle clients
                                            int p = 0;
                                            while (p < clientPWArray.size()) {
                                                outToClient = clientPWArray.get(p);
                                                outToClient.println("1." + checkMesType.getMes(inputMes));
                                                p++;
                                            }
                                       
                                    } else {
                                        System.out.println("bummmm");
                                    }
                           
                           
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                       
                        i++;
                    }
                   
                }
        }
       
    }
Avatar billede langkiller Nybegynder
10. april 2013 - 11:21 #22
kan man ikke tjekke om der kommer noget igennem den readline man kalder og hvis der ikke gør så gå videre med programmet i stedet for at den bare står og venter på input?
Avatar billede langkiller Nybegynder
10. april 2013 - 11:27 #23
jeg har dette loop der koerer igennem de forskellige clients buffered readers


                    int i = 0;
                    while(i < clientBRArray.size()) {

                            inFromClient = clientBRArray.get(i);
                           
                                // ALMINDELIG TEKST BESKED
                           
                                            try {
                                               
                                                if ((inputMes = inFromClient.readLine()) != null) {
                                                   
                                                    if (inputMes.equals("2")) {
                                                        inputMes = inFromClient.readLine();
                                                        messageField.append(inputMes + "\n");
                                                    }
                                                   
                                                }
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                           
                       
                        i++;
                    }

men den stopper bare ved readline uanset om klienten har skrevet noget igennem den. hvordan får man den til at gå videre uden at skulle vente på input fra den bestemte klient i mit loop?
Avatar billede langkiller Nybegynder
10. april 2013 - 15:00 #24
Har tænkt mig at løse mit problem på en anden måde.
Kan en enkelt buffered  reader på server siden, lyrter på mange klienter ?
Avatar billede langkiller Nybegynder
10. april 2013 - 22:56 #25
tror bare jeg vælger at lukke tråden og griber mit problem helt anderledes an. smi et svar, og tak for din hjælp!
Avatar billede arne_v Ekspert
11. april 2013 - 01:42 #26
Saa vidt jeg kan se, saa laeser din traad fra alle klienter.

En klient traad skal kun laese fra en traad men skrive til alle traade.
Avatar billede arne_v Ekspert
11. april 2013 - 01:43 #27
og det er ikke et Java problem men et logisk problem
Avatar billede arne_v Ekspert
11. april 2013 - 01:43 #28
jeg kan godt smide et svar
Avatar billede arne_v Ekspert
11. april 2013 - 01:44 #29
Hvis jeg faar tid kunne jeg godt proeve og lave et eksempel.
Avatar billede langkiller Nybegynder
11. april 2013 - 02:01 #30
det må du meget gerne :) skal jeg vente med at acceptere dit svar så?
Avatar billede arne_v Ekspert
11. april 2013 - 02:48 #31
jeg ved ikke om jeg faar tid - afhaenger lidt af om konen sender mig paa havearbejde i weekenden
Avatar billede langkiller Nybegynder
11. april 2013 - 08:21 #32
Okay, så accepterer jeg bare dit svar nu og så kan du jo skrive eksemplet herinde hvis du får tid. ellers tak for hjælpen.
Avatar billede arne_v Ekspert
14. april 2013 - 04:29 #33

package chat.simple.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {
    private List<ClientHandler> active;
    private ServerSocket ss;
    public Server(int port) throws IOException {
        active = new ArrayList<ClientHandler>();
        ss = new ServerSocket(12345);
    }
    public void run() throws IOException {
        while(true) {
            Socket s = ss.accept();
            ClientHandler cli = new ClientHandler(s, this);
            synchronized(active) {
                active.add(cli);
            }
            cli.start();
        }
    }
    public void sendAll(String msg) {
        synchronized(active) {
            for(ClientHandler ch : active) {
                ch.send(msg);
            }
        }
    }
    public void removeClient(ClientHandler ch) {
        synchronized(active) {
            active.remove(ch);
        }
    }
    public static void main(String[] args) throws IOException {
        Server srv = new Server(12345);
        srv.run();
    }
}



package chat.simple.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientHandler extends Thread {
    private PrintWriter pw;
    private BufferedReader br;
    private Server srv;
    private String usr;
    public ClientHandler(Socket s, Server srv) throws IOException {
        pw = new PrintWriter(s.getOutputStream());
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        this.srv = srv;
        usr = "<no login>";
    }
    public void run() {
        String line;
        try {
            while((line = br.readLine()) != null) {
                if(line.startsWith("USR:")) {
                    usr = line.substring(4);
                } else if(line.startsWith("MSG:")) {
                    String msg = line.substring(4);
                    srv.sendAll(usr + ":" + msg);
                } else {
                    close();
                    return;
                }
            }
        } catch (IOException e) {
            close();
        }
    }
    public void send(String msg) {
        pw.println("MSG:" + msg);
        pw.flush();
    }
    private void close() {
        srv.removeClient(this);
        try {
            br.close();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(usr + ":logout");
    }
}



package chat.simple.client;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Client extends JFrame implements ServerHandler.Display {
    private JTextField un;
    private JButton login;
    private JTextArea msgs;
    private JTextField msg;
    private JButton send;
    private ServerHandler sh;
    public Client() throws UnknownHostException, IOException {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Picture swap");
        getContentPane().setLayout(new BorderLayout());
        un = new JTextField();
        un.setColumns(40);
        login = new JButton("Login");
        JPanel n = new JPanel();
        n.setLayout(new BorderLayout());
        n.add(new JLabel("Username:"), BorderLayout.WEST);
        n.add(un, BorderLayout.CENTER);
        n.add(login, BorderLayout.EAST);
        getContentPane().add(n, BorderLayout.NORTH);
        msgs = new JTextArea();
        msgs.setRows(20);
        getContentPane().add(new JScrollPane(msgs), BorderLayout.CENTER);
        msg = new JTextField();
        msg.setColumns(40);
        send = new JButton("Send");
        JPanel s = new JPanel();
        s.setLayout(new BorderLayout());
        s.add(new JLabel("Message:"), BorderLayout.WEST);
        s.add(msg, BorderLayout.CENTER);
        s.add(send, BorderLayout.EAST);
        getContentPane().add(s, BorderLayout.SOUTH);
        sh = new ServerHandler("localhost", 12345, this);
        sh.start();
        login.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                sh.send("USR:" + un.getText());
            }
        });
        send.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                sh.send("MSG:" + msg.getText());
            }
        });
        pack();   
    }
    public void add(final String msg) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                msgs.append(msg + "\r\n");
            }
        });
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    JFrame f = new Client();
                    f.setVisible(true);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}



package chat.simple.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class ServerHandler extends Thread {
    public static interface Display {
        public void add(String msg);
    }
    private PrintWriter pw;
    private BufferedReader br;
    private Display disp;
    public ServerHandler(String host, int port, Display disp) throws UnknownHostException, IOException {
        Socket s = new Socket(host, port);
        pw = new PrintWriter(s.getOutputStream());
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        this.disp = disp;
    }
    public void run() {
        String line;
        try {
            while((line = br.readLine()) != null) {
                if(line.startsWith("MSG:")) {
                    String msg = line.substring(4);
                    disp.add(msg);
                } else {
                    close();
                    return;
                }
            }
        } catch (IOException e) {
            close();
        }
    }
    public void send(String msg) {
        pw.println(msg);
        pw.flush();
    }
    private void close() {
        try {
            br.close();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Avatar billede langkiller Nybegynder
17. april 2013 - 17:16 #34
Hey tak for det. Det ser godt ud! Har også fået mit peogram til at køre som det skulle :)  avde forresten gået og tænkt over noget omkring servere. Hvis man har en server, eksempelvis en char server, så skal den jo køre hele tiden for at klienterne kan bruge det. Er der en måde at få serveren til at køre uden selv at skulle have en server computer stående og køre derhjemme. Er der nogen form for servixe der tilbyder dette eller kan man gøre noget andet smart for at få det til at køre konstant ? Stiller mest mit spørgsmål af nysgerrighed, ikke noget jeg står og skal bruge lige nu.
Avatar billede langkiller Nybegynder
17. april 2013 - 17:21 #35
Skrevet fra min telefon, derfor der er lidt stavefejl :)
Avatar billede arne_v Ekspert
18. april 2013 - 02:39 #36
Du kan leje en VPS og koere en server daemon paa den.
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