Thread auf Server ausführen

Hi Leute,

ich bastele gerade an ein Java-MATLAB Server. Dieser soll Client-inputs an MATLAB weiterleiten. Dies funktioniert auch soweit! Nun wollte ich einfach dafür sorgen, dass auch mehrer User die Möglichkeit haben gleichzeitig Zugriff auf dem Server zu haben. Da Matlab nur seriell arbeitet, muss ich die Anfragen puffern. Die einfachste Methode schienen mir Threads zu sein! Ich habe zunächt ein Boolean Wert im unteren Thread benutzt, sollte dieser true sein wird gewartet, doch die Methodik funzte nicht wirklich. Ich bekamm auf Client Seite einen Time out , da nicht alle Inputs beim Server ankammen. Nun habe ich einfach “synchronized” benutzt, aber es will nicht recht klappen. Gleiches Problem.
Es könnte damit zusammenhängen, dass ich bei beiden Methoden folgendes

in.close();
out.close();
skt.close();```

auskommentieren muss, da sonst gar nichts klappt. Die Exception sagt nur Socket closed!?

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

import java.util.regex.Pattern;

public class Network implements Runnable {

private ServerSocket serverSkt;
private Socket skt;

private int port = 4444;
private boolean alive = false;

private View view;
private Handling handler = new Handling(this);


public Network(View view) {
    this.view = view;
}

public void listen() {
    try {
        serverSkt = new ServerSocket(port);
        alive = true;

        while(alive) {
            skt = serverSkt.accept();
            new Thread(this).start();
        }
    }

    catch (IOException ex) {
        view.getConsoleTextArea().append("Server connection could not be opened 

" +
"Please make sure port " + port + " is open
" +
“and restart Server”);
view.getStatusMessageLabel().setText(“Server connection error”);
}
}

public void run() {
    
    String outputLine = "";
    String inputLine = "";
    
    synchronized(this){
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
            PrintWriter out = new PrintWriter(new OutputStreamWriter(skt.getOutputStream()));

            String split[] = Pattern.compile("; ").split(in.readLine());

            String type = split[0];
            int bufferSize = Integer.parseInt(split[1]);
            char[] buffer = new char[bufferSize];
            int charLength = in.read(buffer, 0, bufferSize);

            inputLine = new String(buffer, 0, charLength);

            
            view.getConsoleTextArea().append("Message received: " + "

" + inputLine + "

");
outputLine = handler.assign(type, inputLine);
out.print(outputLine.length() + "
" + outputLine);
out.flush();

            view.getConsoleTextArea().append("Message sent: " + "

" + outputLine + "

");

            String[] test = outputLine.split("

");
int j=0;
for (int i = 0; i < test.length; i++) {
j++;
}

            in.close();
            out.close();
            skt.close();
        }

        catch (IOException ex) {
            view.getConsoleTextArea().append("Network error");
            Logger.getLogger(Network.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

public View getView() {
    return view;
}

}


Ich weiß einfach nicht mehr weiter :confused:

Ein Synchroniced bringt dir da nichts, deine Implementierung ist nicht für mehrfach Benutzung ausgelegt.
z.B. dein Socket wird bei jeder neuen Verbindung überschrieben.

Mach lieber für die Abarbeitung einer Verbindung eine eigene Klasse.

Hi, danke für den Tipp!

Ich häng trotzdem etwas in der Luft, da ich mich mit Threads nicht so gut auskenne! Soll in meiner “Network”-Klasse dann auch meine Methode “listen()” sein, dass den Thread dann in einer anderen Klasse startet?

Network:


import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


public class Network {

    private ServerSocket serverSkt;
    private Socket skt;
    private int port = 4444;
    private boolean alive = false;
    private View view;

    private Handling handler = new Handling(this);
    private NetworkInOut networkInOut = new NetworkInOut(this);

    public Network(View view) {
        this.view = view;

    }

    public void listen() {
        try {
            serverSkt = new ServerSocket(port);
            this.setSocket(serverSkt.accept());
            networkInOut.startThread();                      
            
        }

        catch (IOException ex) {
            view.getConsoleTextArea().append("Server connection could not be opened 
" +
                                             "Please make sure port " + port + " is open 
" +
                                             "and restart Server ");
            view.getStatusMessageLabel().setText("Server connection error");
        }
        
    }

    
    public View getView() {
        return view;
    }
    
    public Socket getSocket(){
        return skt;
    }

    public void setSocket(Socket skt){
        this.skt = skt;
    }

    
}```

NetworkInOut:

```import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

public class NetworkInOut implements Runnable{

    private Network networker;
    private View view;
    
    private Handling handler;




    public NetworkInOut(Network networker) {
        this.networker = networker;
        
    }


    public void startThread() {
        new Thread(this).start();

    }
    
    public void run() {
        Window win = new Window();
        win.setVisible(true);
        win.toFront();
        int count=0;

        String outputLine = "";
        String inputLine = "";

        win.getjTextArea1().append(this.toString() + "
" + "vorher: " + count+ "
");
        synchronized(this){

        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(networker.getSocket().getInputStream()));
            PrintWriter out = new PrintWriter(new OutputStreamWriter(networker.getSocket().getOutputStream()));

            String split[] = Pattern.compile("; ").split(in.readLine());

            String type = split[0];
            int bufferSize = Integer.parseInt(split[1]);
            char[] buffer = new char[bufferSize];
            int charLength = in.read(buffer, 0, bufferSize);

            inputLine = new String(buffer, 0, charLength);

            win.getjTextArea1().append("input: " + "
" + inputLine + "
");

            view.getConsoleTextArea().append("Message received: " + "
" + inputLine + "

"); //<--Null Pointer
            outputLine = handler.assign(type, inputLine);
            out.print(outputLine.length() + "
" + outputLine);
            out.flush();

            view.getConsoleTextArea().append("Message sent: " + "
" + outputLine + "

");

            String[] test = outputLine.split("
");
            int j=0;
            for (int i = 0; i < test.length; i++) {
                j++;
            }
            win.getjTextArea1().append(test[j-1]+ "
");

            in.close();
            out.close();

        }

        catch (IOException ex) {
            win.getjTextArea1().append("input: " + "
" + "Network error" + "
");
            view.getConsoleTextArea().append("Network error");
            Logger.getLogger(Network.class.getName()).log(Level.SEVERE, null, ex);
        }


        win.getjTextArea1().append("output: " + "
" + outputLine + "
");
        }

    }

}```


Ich bekomme nun ständig ein Nullpointer beim Pfeil! Was mache ich falsch?

Der Fehler war, dass ich in Network die selbe Instanz verwenden wollte! Habe get und set Methoden in Network eingefügt für die Klasse Handling und View:

Nun bekomme ich folgenden Fehler:

Exception in thread “Thread-10” java.lang.NullPointerException
at java.util.regex.Matcher.getTextLength(Matcher.java:1140)
at java.util.regex.Matcher.reset(Matcher.java:291)
at java.util.regex.Matcher.(Matcher.java:211)
at java.util.regex.Pattern.matcher(Pattern.java:888)
at java.util.regex.Pattern.split(Pattern.java:997)
at java.util.regex.Pattern.split(Pattern.java:1059)
at meinPacket.NetworkInOut.run(NetworkInOut.java:57)
at java.lang.Thread.run(Thread.java:619)

in Zeile 47 in der Klasse NetworkInOut! ;(

du hast den Fehler gleich mitkopiert :wink:
gib deiner Klasse NetworkInOut den Socket mit, deine Serverklasse erzeugt den Socket und gibt ihn mit, danach hat sie nichts mehr mit dem Socket zu tun

Meinst du ich soll die Methode listen aus NetworkINOut ausführen, aber den Socket in Network erzeugen ? D.h. der Serversocket “serverSkt” wir dann in NetworkInOut erzeugt?
Oder was genau meinst du?

nein, statt

    public void listen() {
        try {
            serverSkt = new ServerSocket(port);
            this.setSocket(serverSkt.accept());
            networkInOut.startThread();          
        }
        catch (IOException ex) {
            view.getConsoleTextArea().append("Server connection could not be opened 
" +
                                             "Please make sure port " + port + " is open 
" +
                                             "and restart Server ");
            view.getStatusMessageLabel().setText("Server connection error");
        }
    }```
einfach

public void listen() {
    try {
        serverSkt = new ServerSocket(port);
        Socket s = serverSkt.accept();
        NetworkInOut n = new NetworkInOut(s);
        n.startThread();          
    }
    catch (IOException ex) {
        view.getConsoleTextArea().append("Server connection could not be opened 

" +
"Please make sure port " + port + " is open
" +
"and restart Server ");
view.getStatusMessageLabel().setText(“Server connection error”);
}
}```

Danke für die hilfe! Jetzt muss ich aber den Konstruktor von NetworkINOut umbauen!


    private Socket skt;
    private Network networker;
    
    public NetworkInOut(Socket skt) {
        this.skt = skt;
                
    }

    public void startThread() {
        new Thread(this).start();

    }
    
    public void run() {
        Window win = new Window();
        win.setVisible(true);
        win.toFront();
        int count=0;

        String outputLine = "";
        String inputLine = "";

        win.getjTextArea1().append(this.toString() + "
" + "vorher: " + count+ "
");
        synchronized(this){

        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(networker.getSocket().getInputStream())); <--- hier
            PrintWriter out = new PrintWriter(new OutputStreamWriter(networker.getSocket().getOutputStream()));```

Aber nun bekomme ich eine Nullpointer an der Markierung "hier"! Wenn ich dem Konstruktor Network übergebe, muss ich dass ja auch hier übergeben:

```NetworkInOut n = new NetworkInOut(this.getSocket());```

:(

nein du kehrst immer wieder zu deinem Problem zurück
Dein komplettes Programm basiert auf einem ServerSocket und einem Socket, jedoch wird der Socket bei einer 2. Verbindung überschrieben.
Du musst alles was nach dem Verbindungsaufbau passiert von dem Serverkram trennen.

Heißt das:

  1. [in Network] ich baue die Verbindung auf
  2. [in Network] ich lese den Kram aus (da Socket Infos benötige, baue ich den BufferReader auch in Network)
  3. [in NetworkInOut] ich hole mir den Input aus Network
  4. [in NetworkInOut] und schicke es an MATLAB
  5. [in NetworkInOut] und dann an den Client

So müsste ich der Socket nur an dem PrintWriter übergeben werden!

Hab ich es jetzt verstanden:o:o:o:o

nein
Du nimmst die Verbindung in Network entgegen und ALLLES andere passiert in InOut