Avatar billede quiw Nybegynder
23. juni 2008 - 20:01 Der er 16 kommentarer og
1 løsning

Server/klient

Hejsa eksperter, nu har jeg kæmpet med adskillige versioner af server/klient princippet, ud fra hvad jeg har kunne lære af andres problemer, men det kan bare ikke lykkedes mig, at lave noget som virker bare lidt .. Det ender altid med, at den kun vil sende/modtage nogle gange ..
- Så nu spørger jeg, er der nogle som kan give mig et eksempel, på en yderst simpel version af klient/server, hvor klienten automatisk har et loop der modtager konstant, og det samme med serveren, således at når de er forbundet, kan de sende og modtage så tosset de vil, uden at vente på hinanden .. Helst gerne med multithread, således at den kan acceptere flere connections ..

- har virkelig kæmpet hele dagen, men uden held.
Avatar billede arne_v Ekspert
23. juni 2008 - 20:22 #1
http://www.eksperten.dk/artikler/515 har nogle eksemler paa client/server over socket !

(artiklens formaal er at vise .NET---Java men eksemplerne virker fint med
Java---Java)
Avatar billede quiw Nybegynder
23. juni 2008 - 21:28 #2
På klient delen, har jeg banket det her sammen:

public void startnet(){
        try {
              s = new Socket("127.0.0.1", 12345);
              pw = new PrintWriter(s.getOutputStream());
              br = new BufferedReader(new InputStreamReader(s.getInputStream()));
              recvThread = new recvNet();
              recvThread.start();
        }
        catch (NumberFormatException e){
            e.printStackTrace();
        }
        catch (UnknownHostException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
public void send(String msg){
        pw.println(msg); 
        pw.flush();
    }
public void stopnet(){
        try{
              br.close();
              pw.close();
              s.close();
        }
        catch (NumberFormatException e){
            e.printStackTrace();
        }
        catch (UnknownHostException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

- Det fungere udemærket, men nu vil jeg gerne have et recieve loop til at køre i baggrunden, så derfor opretter den tråden:

package Main;

import java.net.*;
import java.io.*;
import Main.Client;

public class recvNet extends Thread
{
    public void run(){
        String line;
        while(true){
            //Modtag kommando fra serveren, og put i line.
            //Tjek om line betyder noget, og gør dit og dat.
        }
    }
}

- Men er lidt blank nu, hvordan overføre jeg socket, så den kan lytte på den socket, i den nye tråd?
Avatar billede quiw Nybegynder
23. juni 2008 - 21:58 #3
Jeg har nu fået tråden bygget sådan her sammen:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package Main;

import java.io.*;
import java.net.*;
import Main.Client;

public class recvNet extends Thread
{
    Socket b;
   
    recvNet(Socket s){
      b=s;
    }
    public void run(){
        System.out.print("Tråd startet med socket: "+b);
        try{               
            BufferedReader br = new BufferedReader(new InputStreamReader(b.getInputStream()));
            while(true){
                System.out.print("Modtog: "+br.readLine());
            }               
        }
        catch (NumberFormatException e){           
            e.printStackTrace();       
        }
        catch (UnknownHostException e) {           
            e.printStackTrace();
        }
        catch (IOException e){           
            e.printStackTrace();       
        }
    }
}


- Men jeg modtager intet fra serveren, på trods af at serveren sender afsted :S
Avatar billede quiw Nybegynder
23. juni 2008 - 22:17 #4
Neeeej, problemet er løst .. Det var mig, som havde glemt at få flush efter beskeden hos serveren.
Avatar billede quiw Nybegynder
23. juni 2008 - 22:31 #5
Men, hvordan undgår jeg en masse grimme fejlmeddelser på serveren hvis klienten lukker webbrowseren? Og hvordan får jeg serveren til at skrive en besked til en bestemt klient?
Avatar billede arne_v Ekspert
24. juni 2008 - 01:03 #6
Hvis serveren mister forbindelse til en client så skal du catch den exception.
Avatar billede arne_v Ekspert
24. juni 2008 - 01:03 #7
Hvis serveren skal skrive til bestemte klienter, så skal den have referencer til dem.
Avatar billede arne_v Ekspert
24. juni 2008 - 01:05 #8
Følgende eksempel sender til alle klienter:

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

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(9999);
            while(true) {
                Socket s = ss.accept();
                ClientHandler cli = new ClientHandler(s);
                cli.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

class ClientHandler extends Thread {
    private BufferedReader br;
    private PrintWriter pw;
    public ClientHandler(Socket s) {
        try {
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            pw = new PrintWriter(s.getOutputStream(), true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void run() {
        try {
            String line;
            while((line = br.readLine()) != null) {
                System.out.println(line);
                pw.println(line);
                pw.flush();
            }
        } catch (IOException e) {
            // nothing
        } finally {
            System.out.println("Client leaving");
        }
    }
}

Hvis klienter har et navn, så kan det nemt modificeres til at sende til en bestemt klient.
Avatar billede quiw Nybegynder
24. juni 2008 - 01:25 #9
Hvor er det nøjagtigt at den sender til alle? Kan ikke lige spotte, hvad forskellen er mellem mit og dit ..
Avatar billede quiw Nybegynder
24. juni 2008 - 01:29 #10
Hm, den sender ikke til alle klienterne, de andre applets, modtager intet .. Hm .. Og det går egentlig ret langsomt, i forhold til min server i C++ ..
Avatar billede arne_v Ekspert
24. juni 2008 - 02:34 #11
Sorry - forkert kode - her er den rigtige:

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

public class Server {
    public static void main(String[] args) {
        try {
            List lst = new ArrayList();
            ServerSocket ss = new ServerSocket(12345);
            while(true) {
                Socket s = ss.accept();
                ClientHandler cli = new ClientHandler(s, lst);
                cli.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

class ClientHandler extends Thread {
    private Socket s;
    private BufferedReader br;
    private PrintWriter pw;
    private List lst;
    private String user;
    public ClientHandler(Socket s, List lst) {
        try {
            this.s = s;
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            pw = new PrintWriter(s.getOutputStream(), true);
            this.lst = lst;
            user = "not logged in";
            lst.add(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void run() {
        try {
            String line;
            while((line = br.readLine()) != null) {
                if(line.substring(0,6).equals("LOGIN ")) {
                    user = line.substring(6);
                    System.out.println(user + " login");
                } else if(line.substring(0,5).equals("SEND ")) {
                    String msg = line.substring(5);
                    for(int i = 0; i < lst.size(); i++) {
                        ClientHandler cli = (ClientHandler)lst.get(i);
                        if(cli != this) {
                            cli.send(msg);
                            System.out.println(msg + " send to " + cli.user);
                        }
                    }
                } else {
                    System.out.println("Unknown command : " + line);
                }
            }
        } catch (IOException e) {
            // nothing
        } finally {
            lst.remove(this);
        }
    }
    public void send(String msg) {
        pw.println(msg);
    }
}
Avatar billede quiw Nybegynder
25. juni 2008 - 12:04 #12
Det fungere udemærket, men ved ikke om det blot er mig, men synes at en C++ server kører betydentligvis hurtigere end javaserver .. Er det bare mig?
Avatar billede quiw Nybegynder
25. juni 2008 - 17:08 #13
Hov, og endnu en fejl, den sender kun beskeden hver anden gang .. Hvis man benytter send("streng"), sender den kun hver anden gang.
Avatar billede arne_v Ekspert
26. juni 2008 - 04:35 #14
Der burde ikke være nogen nævneværdig forskel på dette Java program og et tilsvarende
C++ program.

Flaskehalsen er netværks delen.
Avatar billede arne_v Ekspert
26. juni 2008 - 04:37 #15
Da jeg testede sendet den hver gang.

Når jeg kigger lidt på koden syne sjeg dog at der mangler et flush kald. Prøv evt. med det.
Avatar billede quiw Nybegynder
26. juni 2008 - 11:15 #16
Jeg forsøgte faktisk med flush her i går middags, det virkede hurtigere, men løste ikke problemet, men jeg begav mig ud i at skrive det hele forfra, med stor inspiration fra dit eksempel, og der løste problemet sig selv.. Så nu virker det hele korrekt :) Du må gerne ligge et svar.
Avatar billede arne_v Ekspert
26. juni 2008 - 11:39 #17
svar
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