Socket Compilierungsproblem

burgadon

Mitglied
Moinsen.

Habe vor 2 Tagen mit dem programmieren von Netzwerken begonnen und wollte mal ein erstes Testprogramm mit Socket und ServerSocket schreiben:

CLIENT:
Java:
//CLIENT
import java.io.*;
import java.net.*;

public class Client{
    public static void main(String[] args){
    Client client = new Client();
     try {
         client.socketKonstruieren();
     } catch (IOException e) {
         e.printStackTrace();
     }
    }

    void socketKonstruieren() throws IOException {
    //Socket auf localhost port 1000 konstruieren
    String ip = "127.0.0.1"; //localhost
    int port = 1000;
    Socket socket = new Socket(ip,port);
    }
    
    void senden(String textSenden) throws IOException {
    //Etwas über den Socket versenden
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    out.write(textSenden);
    //Zeilenumbruch senden
    out.newLine();
    out.flush();
    }

    String empfangen() throws IOException {
    //BufferedReader konstruieren
    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    //Eine Zeile lesen
    String textEmpfangen = in.readLine();

    //Text ausgeben
    System.out.print("Eingegangener Text: ");
    
    System.out.println(textEmpfangen);

    return textEmpfangen;

    //Schliessen aller offenen Reader und Writer, der Socket wird dabei automatisch geschlossen
    socket.close();
    //in.close();
    }



SERVER:
Java:
//SERVER
import java.io.*;
import java.net.*;

public class Server{
  public static void main(String[] args){

  int port = 1000;
  
  //Server starten
  ServerSocket server = new ServerSocket(port);

    while(true) {
      //Warten auf eine neue Verbindung
      Socket s = server.accept();

      //Neue Verbindung ist da, wir lesen einfach aus,
      //was sie uns so schickt und schicken dann alles in grossbuchstaben wieder zurück
      BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
      String text = in.readLine();

      BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
      out.write(text.toUpperCase());
      out.newLine();
      out.flush();

      //Aufräumen
      out.close();
      in.close();
      server.close();
    }
  }
}

Jetzt habe ich ein Problem. Beim compilieren des client-codes bekomme ich ne Fehlermeldung, sobald ich socket.getInputStream()/socket.getOutputStream() oder socket.close benutze. Warum weiß ich nicht. (Habe den Server-Code mal mit dazugepackt. Der ist aber noch nicht angepasst :S)

Kann mir jemand vlt helfen. Wäre sehr nett. Vielen Dank schonmal
LG Burgadon
 

Tobse

Top Contributor
Und WAS für eine Fehlermeldung ist das? *Glaskugel raushohl* Hmm... die is wohl kaputt, da must du uns helfen...
 

wef34fewrg

Aktives Mitglied
:toll:

Da brauchst du keine Fehlermeldung raushauen. Wenn du dir den code ansiehst wirst du schnell erkennen, dass "socket" lokal angelegt wird. So bald du aus socketKonstruieren() rauskommst ist das Socket doch gar nicht mehr anzusprechen :)
 

Tobse

Top Contributor
Und in der Main solltest du wenn du dann die Variable hast mehrmals ein
Code:
unreported java.io.IOException
bekommen.

[OT]
Da brauchst du keine Fehlermeldung raushauen

Es geht mir ja blos ums Prinzip. Blos sagen "Das tut nicht, sagt mir mal warum" ohne ein Mindestmaß an Infos für uns finde ich einfach schlechte manieren.

[/OT]
 

burgadon

Mitglied
@Rock45

Aber da ich im konstruktor die Methode Konstruieren doch aufrufe, müsste das dann nicht trotzdem global gelten?

Fehlermeldung war:

Code:
Client.java:24:72: error: cannot find symbol
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                                                                       ^
  symbol:   variable socket
  location: class Client
Client.java:33:70: error: cannot find symbol
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                                                     ^
  symbol:   variable socket
  location: class Client
Client.java:45:9: error: cannot find symbol
        socket.close();
        ^
  symbol:   variable socket
  location: class Client
3 errors

Das mit der Fehlermeldung war mein Fehler. Sorry dafür. Die Unreported IOException hab ich bisher nicht gehabt...
 

Tobse

Top Contributor
Aber da ich im konstruktor die Methode Konstruieren doch aufrufe, müsste das dann nicht trotzdem global gelten?

In Java ist garnichts global. Dinge, die im Konstruktor stehen, passieren wenn du das Objekt erstellst. Aber der Gültigkeitsbereich von Variablen ist unabhängig davon, WO sie deklariert werden.
Für die ganze Klasse gilt die Variable dann, wenn du sie als solche deklarierst: Als Klassenvariable.
 

rme

Top Contributor
Variablen, die du innerhalb einer Methode deklarierst, sind auch nur in dieser Methode gültig - deshalb kennt der Compiler sie in der anderen Methode nicht. Wenn sie innerhalb der ganzen Instanz gültig sein soll, musst du sie als Instanzvariable deklarieren, d.h. auf Ebene der Klasse statt innerhalb der Methode. So, wie du es bei der Variable client gemacht hast.
 

wef34fewrg

Aktives Mitglied
Und in der Main solltest du wenn du dann die Variable hast mehrmals ein
Code:
unreported java.io.IOException
bekommen.

[OT]

Es geht mir ja blos ums Prinzip. Blos sagen "Das tut nicht, sagt mir mal warum" ohne ein Mindestmaß an Infos für uns finde ich einfach schlechte manieren.

[/OT]

Dein Prinzip habe ich eingehalten. Ich habe eine Aussage getätigt und sie doch dann auch begründet. Wenn ich mehr mache, müsste ich das ja schon selber schreiben. ;)

@Rock45

Aber da ich im konstruktor die Methode Konstruieren doch aufrufe, müsste das dann nicht trotzdem global gelten?

Die Sache mit dem global wird ja schon beantwortet.
Das größte Problem. DU HAST GAR KEIN KONSTRUKTOR!

Java:
//Deine Klasse Client unter Herausnahme aller Methoden.
public class Client{
   
    }

Wie schon beschrieben, haben Variablen innerhalb einer Methode nur eine lokale Sichtbarkeit. Sobald du die Methode verlässt sind die Variablen nicht mehr ansprechbar.
Im Fall von Socket entsteht sogar das Problem, dass du die Ressource gar nicht schließt und auch nicht mehr schließen kannst, jedenfalls mit der Programmlogik.

Wenn ich die Klasse jetzt auch so durchlese kommen auch andere Probleme mit Exceptions die du nicht behandelst und mein fave?

Java:
 String empfangen() throws IOException {
    //BufferedReader konstruieren
    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    //Eine Zeile lesen
    String textEmpfangen = in.readLine();
 
    //Text ausgeben
    System.out.print("Eingegangener Text: ");
   
    System.out.println(textEmpfangen);
 
    return textEmpfangen;
  //wird niemals erreicht ;)
    socket.close();
    //in.close();[/U][/B]
    }

Da musst du echt noch was dran basteln!
 
Zuletzt bearbeitet:

burgadon

Mitglied
Ja, wie gesagt, hab ja erst vor ein paar Tagen mit den sockets angefangen und Java hab ich davor über ein Jahr nicht mehr benutzt :D

Aber danke auch für eure nette und nützliche Hilfe. Top "Service" ;)

LG
 

burgadon

Mitglied
So habe nun ein funktionierendes Client-Server Konzept:

Server:
Java:
// Server
import java.net.*;
import java.io.*;

public class Server {
   public static void main(String[] args) {
       Server server = new Server();
       //while (true){
       try {
           server.test();
       } catch (IOException e) {
           e.printStackTrace();
       }//}
   }

   void test() throws IOException {
       int port = 1000;
       ServerSocket serverSocket = new ServerSocket(port);
       Socket client = warteAufAnmeldung(serverSocket);
       String nachricht = leseNachricht(client);
       System.out.println(nachricht);
       String zuSenden = "This world is cruel!";
       schreibeNachricht(client, zuSenden);
   }

   Socket warteAufAnmeldung(ServerSocket serverSocket) throws IOException {
       Socket socket = serverSocket.accept();
       return socket;
   }
   
   String leseNachricht(Socket socket) throws IOException {
       BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
       char[] buffer = new char[200];
       int anzahlZeichen = bufferedReader.read(buffer, 0, 200);
       String nachricht = new String(buffer, 0, anzahlZeichen);
       return nachricht;
   }
   
   void schreibeNachricht(Socket socket, String nachricht) throws IOException {
       PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
       printWriter.print(nachricht);
       printWriter.flush();
   }
}

Client:
Java:
// Client

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

public class Client {
    public static void main(String[] args) {
       Client client = new Client();
       try {
           client.test();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }

    void test() throws IOException {
       String ip = "192.168.0.1"; //IP des Servers
       int port = 1000;
       Socket socket = new Socket(ip,port); // verbindet sich mit Server
       String zuSendendeNachricht = "Hello, world!";
       schreibeNachricht(socket, zuSendendeNachricht);
       String empfangeneNachricht = leseNachricht(socket);
       System.out.println(empfangeneNachricht);
    }

    void schreibeNachricht(Socket socket, String nachricht) throws IOException {
       PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
       printWriter.print(nachricht);
       printWriter.flush();
    }

    String leseNachricht(Socket socket) throws IOException {
       BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
       char[] buffer = new char[200];
       int anzahlZeichen = bufferedReader.read(buffer, 0, 200);
       String nachricht = new String(buffer, 0, anzahlZeichen);
       return nachricht;
    }
}

Jetzt meine Frage: Wie kann ich das bewerkstelligen, dass der Server nach verschicken/empfangen der Nachricht empfangsbereit bleibt. Wenn ich die (auskommentierte) while-Schleife im Server-Code im try&catch-Teil im Konstruktor benutze, bleibt der Server zwar bestehen, aber die nachricht des Clienten wird beim Server nicht mehr angezeigt.
Und wie kann ich ip, port und die zu sendende nachricht vom User eingeben lassen? Dazu reichen meine Schulkentnisse nicht aus ;(

Vielen Dank schonmal für eure Hilfe
 
Zuletzt bearbeitet:

Tobse

Top Contributor
Ach komm, streng mal deine grauen Zellen ein wenig an! Um empfangsbereit zu bleiben helfen dir vielleicht [JAPI]java.lang.Thread[/JAPI] und [JAPI]java.lang.Runnable[/JAPI] aber das mit der IP kriegst du 100% selbst hin.
 

burgadon

Mitglied
Ach komm, streng mal deine grauen Zellen ein wenig an! Um empfangsbereit zu bleiben helfen dir vielleicht [JAPI]java.lang.Thread[/JAPI] und [JAPI]java.lang.Runnable[/JAPI] aber das mit der IP kriegst du 100% selbst hin.

Das mit der IP geht wahrscheinlich überVariablen außerhalb der Methoden, oder?

Da ich nur Schulinformatik hatte und Java dort nur ein halbjahr lang gemacht wurde, weiß ich nicht, was [JAPI]java.lang.Thread[/JAPI] und [JAPI]java.lang.Runnable[/JAPI] ist/sind. Kannst du mir da weiterhelfen?

LG
 

wef34fewrg

Aktives Mitglied
Das mit der IP geht wahrscheinlich überVariablen außerhalb der Methoden, oder?

Da ich nur Schulinformatik hatte und Java dort nur ein halbjahr lang gemacht wurde, weiß ich nicht, was [JAPI]java.lang.Thread[/JAPI] und [JAPI]java.lang.Runnable[/JAPI] ist/sind. Kannst du mir da weiterhelfen?

LG

Die "Variablen außerhalb der Methode" :D ist richtig. Da kannst du dir die Sachen speichern und dann nutzen. ;)
Beim zweiten Problem solltest du aber selber bisschen auf die Sprünge kommen. Das Forum soll ja eine Hilfestellung bieten und keine Anlaufstelle für ein Programmiertutorial. ;)
Google mal nach den Klassen, die du von "Tobse" erhalten hast, und danach vielleicht nach Parallele Programmierung und (bist du da noch nicht darauf gekommen?) nach "TCP Client/Server Java" "TCP Beispiel", etc. Da findest du alles was du brauchst.

[OT]Hab bei meiner alten Uni mal den Antrag gestellt "googeln" als Pflichtfach einzuführen. ;)[/OT]

Da ich jetzt aber auch nicht unfair sein will. In deinem Programm hast du einen Thread, der deine Programmlogik durchläuft. Dieser Thread ist ausreichend für einfache Programme, die sequentiell abgearbeitet werden müssen (Also spring zu A tue dieses, spring dann zu B und tue jenes und spring dann wieder zu A um was ganz anderes zu tun etc).

Da du allerdings zwei unabhängige Programmteile hast, in deinem Fall Server und Client, brauchst du zwei Threads, die diesen Programmteilen eine parallele Ausführung ermöglicht.
Wenn du zwei Threads am Laufen hast, kann der eine die while Schleife auf Serverseite durchlaufen und der Andere die Clientseite abarbeiten. So weit, so gut?
 

Neue Themen


Oben