von Socket-Stream lesen

Status
Nicht offen für weitere Antworten.
A

Andreas

Gast
Hallo!

Also ich habe noch wenig Ahnung von Java, einige Dinge kommen mir durch die Objektorientierung etwas seltsam vor ;-)

Ich habe ein Beispiel-Programm, einen einfachesn Socket-Server, der einfach nur dei gelesen Strings zurück auf das Socket schreibt. Jetzt war das Beispiel wohl schon etwas älter, das heißt die Methode readline von InputStreamReader ist wohl deprecated. Das geht zwar, aber ich will ja nicht direkt so anfangen, sondern das dann auch richtig machen. Also habe ich in der Doku nachgesehen, und da stand, dass ich

DataInputStream d = new DataInputStream(in);

durch

BufferedReader d = new BufferedReader(new InputStreamReader(in));

ersetzen soll. Gut, das habe ich jetzt mal gemacht, was sagt Ihr dazu:



Code:
import java.io.*;
import java.net.*;

public class server  {

  public static void main(String args[]) {

    int anz = 1;
    try {
        ServerSocket ss = new ServerSocket(7788);
        while(true) {
          Socket sverb = ss.accept();
          System.out.println(" Verbindung " + anz);
          new ServerThread(sverb,anz).start();
          anz++;
        }
    }
    catch (Exception e) {
        System.out.println(e);
    }
  }
}

class ServerThread extends Thread {
  Socket sverb;
  int    nverb;

  ServerThread(Socket s , int n) {
    this.sverb = s;
    this.nverb = n;
  }

  public void run () {

    try {

        //DataInputStream in =
        //   new DataInputStream(sverb.getInputStream());    
        BufferedReader in = 
            new BufferedReader(new InputStreamReader(sverb.getInputStream()));
        PrintStream out =
           new PrintStream(sverb.getOutputStream());
        out.println( "Hallo - Willkommen beim Simple-Echo-Server!\r\n");

        boolean weiter = true;
        while (weiter) {
           String str = in.readLine();
           if (str == null) weiter = false;
           else {
              out.println("Enter ciao "+nverb+" : "+str);
              if (str.trim().equals("ciao")) {
                  out.println( "Der Verbindung wurde beendet.");
                  weiter=false;
              }
              if (str.trim().equals("shutdown")) {
                  out.println(" Server wird beendet");
                  System.out.println("Server wurde beendet");
                  System.exit( 0 );
              }
           }
        }
        sverb.close();
    }
    catch (IOException e) {
      System.out.println(e);
    }
  }
}

Und es funktioniert auch, nur kommt mir das nicht so effizient vor für jede Zeile ein neues Objekt zu initialisieren, oder? Würdet Ihr das anders machen?

Durch die Eingabe von "shutdown" lasse ich den Server beenden.

Gibt es in Java eigentlich auch eine einfache Möglichkeit einen solchen Server mit Stack und Worker-Threads zu implementieren? Also dass man die eingehenden Anfragen auf einen virtuellen Stapel legt den eine festgelegte Anzahl an Worker-Threads abarbeitet?

Welche Klassen/Methoden würdet Ihr zum schreiben und lesen vom Socket verwenden?


Grüße
Andreas
 

Stefan1200

Top Contributor
Also auf dem ersten Block sieht dein Source gut aus. PrintStream und BufferedReader verwende ich für meinen kleinen HTTP Server auch.

Zu deiner anderen Frage (Stack, usw.) kann ich leider nichts sagen.
 
G

Guest

Gast
Hallo!

Danke, das ist schonmal gut zu hören ;-)

Ich habe das jetzt auch schon in anderen Beispielen gesehen. Naja, Sinn und Zweck der Übung ist es dass ich ein bisschen mehr über Java, udn dort vor alle im Zusammenspiel mit HTTP, und über Streams und Tolkens lerne. Daher habe ich das ganze jetzt etwas weiter entwickelt, und zwar will ich einen einfachen HTTP-Proxy programmieren.

Hierbei habe ich 2 Probleme:
1. Binäre Daten (Bilder, gzip...) werden fehlerhaft übertragen
2. Ich finde keine vernünftige Möglichkeit die HTTP-Header zu parsen.

Zum lesen verwende ich

Code:
BufferedReader in =
    new BufferedReader(new InputStreamReader(sverb.getInputStream()));

Dann lese ich in einer Schleife mit

Code:
line = in.readLine();


Die erste Zeile des HTTP-Requests vom Browser parse ich so
Code:
  StringTokenizer tokenizer = new StringTokenizer( line );
  methode = tokenizer.nextToken();
  url = tokenizer.nextToken();
  proto = tokenizer.nextToken();

  URL u = new URL( url );
  host = u.getHost();
  path = u.getPath();
  query = u.getQuery();


Die Frage ist jetzt, wie kann ich die restlichen Header-Zeilen parsen. Bis jetzt schicke ich die einfach unverändert weiter, aber z.B. "proxy-conection", muss ich rauslöschen und dafür "connection" einfügen. Ich würde aber auch gerne andere Header lesen, entfernen oder verändern können. Ich kann einfach nicht glauben dass das ganze nur so kompliziert geht wie ich es in der ersten Zeile des Requests gemacht habe, außerdem ist das fehleranfällig. Es gibt zwar die spezielle URL und URLConnection Klasse, aber die sind IMHO nicht flexibel genug.

Das Problem ist grundsätzlicher Art. Sollte ich den Request zeilenweise parsen, oder sollte ich das anders einlesen? Wie bekomme ich die einzelnen Header am einfachsten aus dem Request/Response?

Das 2. Problem besteht darin, dass binäre Daten nicht korrekt übertragen werden. Das betrifft also nur den eingehenden Stream vom Webserver und den ausgehenden Stream an den Client. Bisher verwende ich sowohl readline() zum lesen und println() zum schreiben auf den Stream. Wobei, theoretisch müsste readline() binäre Daten ja in einer Zeile einlesen, und println() dann auch als eine Zeile ausgeben, Problem würe dann evtl. ein Zeilenumbruch zu viel am Ende. Wenn Zeichen innerhalb binärer Daten als Umbruch interpretiert würden, müsste das doch entsprechend bei println() genaus wiederhergestellt werden. Naja, aber man sollte es wohl lieber anders machen, kann man nicht den eingehenden Stream direkt zum Client weiterleiten?

Naja, die Konzepte von Streams und Tokens sind noch recht neu für mich, ich bin mir sicher dass das sehr mächtig ist und sich das ganze erheblich schöner erledigen lässt, nur komme ich nicht so recht dahinter, wie ;-)

Wie sollte man die Daten einlesen und ausgeben (zeilenweise, byte-weise oder geht das auch anders)?

Wie parse ich die HTTP-Header aus dem Stream?

Und noch eine Frage, womit kann ich in einem String einen Teilstring gegen einen anderen String ersetzen, also ageal an welcher Position, oder besser direkt alle Teilstrings?


Ja, viele Fragen und Probleme, ich hoffe Ihr habt den ein der andern Tipp für mich ;-)
Oder kennt jemand von Euch ein Tutorial oder sonstiges was mir in dieser Richtung helfen kann, vielleicht auch im Hinblick speziell auf einen HTTP.Proxy oder Teiprobleme?

Der aktuell komplette Code meines HTTP-Proxies:

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

public class proxy {

    public static void main(String args[]) {

        int anz = 1;
        try {
            ServerSocket ss = new ServerSocket(7788);
            while(true) {
                Socket sverb = ss.accept();
                System.out.println(" Verbindung " + anz);
                new ServerThread(sverb,anz).start();
                anz++;
            }
        }
        catch (Exception e) {
            System.out.println(e);
        }
    }
}

class ServerThread extends Thread {
    Socket sverb;
    int    nverb;

    ServerThread(Socket s , int n) {
        this.sverb = s;
        this.nverb = n;
    }

    public void run () {

        try {

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

            PrintStream out =
                new PrintStream(sverb.getOutputStream());

            boolean weiter = true;
            boolean firstline = true;
            String retline = "";
            String line = "";
            String methode = "";
            String url = "";
            String host = "";
            String path = "";
            String query = "";
            String proto = "";
            String request = "";

            while (weiter) {
        
                line = in.readLine();
                if (firstline) {

                    StringTokenizer tokenizer = new StringTokenizer( line );
                    methode = tokenizer.nextToken();
                    url = tokenizer.nextToken();
                    proto = tokenizer.nextToken();
                         
                    URL u = new URL( url );
                    host = u.getHost();
                    path = u.getPath();
                    query = u.getQuery();
           	   
                    firstline = false;
                    continue;
                }
                else {
                    if (line.trim().equals("")) {
                   
                        try {
                  
                            Socket t = new Socket( host, 80 );

                            BufferedReader from_serv = new BufferedReader(
                                new InputStreamReader( t.getInputStream()));

                            PrintStream to_serv = new PrintStream( t.getOutputStream() );
                            to_serv.println( methode + " " + path + "?" + query + " " + proto + "\r\nhost: " + request );
                            while (true) {
                                retline = from_serv.readLine();
                                if (retline == null) {
                                    break;
                                }
                                out.println( retline );
                            }
                        }
                        catch (IOException e) {
                            System.out.println(e);
                        }   
                                     
                        break;
                    }
                    else {
                        request += line + "\r\n";
                        continue;
                    }
                }
            }
            sverb.close();
        }
        catch (IOException e) {
            System.out.println(e);
        }
    }
}


Vielen Dank im voraus!


Grüße
Andreas[/code]
 

Stefan1200

Top Contributor
Puh, in meinem HTTP Server pflücke ich einfach nur den für mich relevanten Teil mit indexOf und substring raus. Einem simplen HTTP1.0 Server, wie meiner, interessiert ja nur die erste Zeile ;-)

Zum Thema Netzwerk Programmierung kann ich dir aber die Büchlein "Handbuch der Java Programmierung" von Guido Krüger, und "Java ist auch nur eine Insel", 2. Auflage, empfehlen.
Kostenlose Download Links:
http://www.javabuch.de
http://www.galileopro.de/openbook/javainsel2/galileocomputing_javainsel2.zip

Direkt Links zum Thema Netzwerk Programmierung:
http://www.rz.fhtw-berlin.de/hjp3/k100283.html#kapitelnetzwerkprogrammierung
http://www.galileocomputing.de/openbook/javainsel2/java_160000.htm

Auf Proxy Programmierung gehen die zwar nicht direkt ein, aber vielleicht gibt es dort ja noch andere brauchbare Infos für dich.
 
A

Andreas Korthaus

Gast
Ah, Danke für die Links, ab das Addison-Wesley Buch habe ich gar nicht mehr gedacht, das waren genau dei beiden Bücher die ich am besten fand, habe mich aber für das Insel-Buch entschieden, da es mir vom Schreibstil und von der Aufmachung besser gefallen hat. Außerdem behandelt es ein paar Themen mehr, unter anderem JSP/Servlets, was mich eben besonders interessiert. Auf der anderen Seite ist das Addison-Wesley Buch in en anderen Kapitlen noch ausführlicher, was man an dem Netzwerk-Kapitel schön sieht. Der dort entwickelte Webserver ist sehr interessant. Wobei ich eigentlich weniger Probleme mit NEtzwerk-Programierung an sich habe, das kenne ich schon ausführlichst von PHP und auch ein bisschen von C, ich habe eher Problöeme mit den Datentypen, Streams und Tolkenizer. Ich habe z.B. eine sehr effektive Möglichkeit gefunden den Response-Stream vom Webserver direkt byteweise an den Client weiterzugeben. Wie ich es vorher gemacht habe, zeilenweise als Striungs einlesen udn genaus wieder ausgeben war Mist udn hat bei größeren Seiten meine CPU für einige Sekunden lahmgelegt ;-)
Nur habe ich jetzt ein anderes Problem. Und zwar wollt eich es mal Spasseshalber Probieren Worte im Response-Body gegen andere auszutauschen und an den Client zu senden. Das ist sehr witzig, ich habe z.B. mal "Computer" durch "Wandschrank" ersetzt, dann wird im Browser überall wo der Server "Computer" schreibt "Wandschrank" hingeschrieben ;-) Nur funktioniert da snicht so richtig. Ich habe immer eine gewise Anzahl Bytes in einen String umgewandelt, das Wort ersetzt und wieder zurück in Bytes umgewandelt. Naja, hat nicht so richtig funkitoniert, die Webseiten kamen dann zerschosen im Browser an. Lag glaube ich an der Länge der Bytes di eich vermutlich beim Schreiben faslch angegebenhabe.

So sieht es aus wenin es wunderbar funktioniert (mit dem Durchreichen der Bytes):


Code:
byte[] buf = new byte[4096];
int bytesIn = 0;
while ( ((byteCount < contentLength) || (waitForDisconnect))
							    && ((bytesIn = from_serv.read(buf)) >= 0) )
{
    out.write(buf, 0, bytesIn);
    byteCount += bytesIn;
}

Wie gesagt, sehr einfach und effektiv. Jetzt habe ich versucht Teilstrings zu ersetzen:

Code:
byte[] buf = new byte[4096];
int bytesIn = 0;
String str_buf = "";
if (contentType.equals("text/html")) {
    while ( ((byteCount < contentLength) || (waitForDisconnect))
							    && ((bytesIn = from_serv.read(buf)) >= 0) )
    {
        String str = new String(buf);
        str = str.replaceAll("Computer", "Wandschrank");
        out.write(str.getBytes(), 0, str.length());
        byteCount += bytesIn;
    }
}


Da scheint es ein Problem, was vermutlich mit dem Unterschied von Byte-Arrays und Strings zu tun hat, zu geben. (Ich unterdrücke extra die gip-Header des Clients so dass ich plain-Text vom Server erhalte, außerdem filter ich ob es auch wirklich HTML ist, mit Hilfe des Content-type headers.). Oder sollte ich das doch zeilenweise als Strings einlesen, aber das war so fürchterlich langsam. Ich weiß auch nicht ob es Sinn hat die Daten erst komplett in einen String zu lesen, dann "replace" und danach in Byte umwandeln und weiterschiken?

Grüße
Andreas
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Audio Stream läuft auf :connection abort: socket write error Java Basics - Anfänger-Themen 2
izoards Socket Kommunikation Java Basics - Anfänger-Themen 16
Nina Pohl Ein Vorgang bezog sich auf ein Objekt, das kein Socket ist Java Basics - Anfänger-Themen 6
G Socket Verbindung aufbauen Java Basics - Anfänger-Themen 11
S Bilder über Socket Senden Java Basics - Anfänger-Themen 1
S Asynchrone Socket-Abfragen Java Basics - Anfänger-Themen 5
Meeresgott OOP Socket Verbindung richtig Kapseln Java Basics - Anfänger-Themen 0
O Socket by reference übergeben Java Basics - Anfänger-Themen 0
J Socket schließen - Ist eine SocketException unumgänglich? Java Basics - Anfänger-Themen 4
D Socket ---> Server Socket worauf muss ich achten? Java Basics - Anfänger-Themen 2
N Socket-Programmierung Java Basics - Anfänger-Themen 4
M wait/notify bei Socket Java Basics - Anfänger-Themen 4
B Input/Output Socket I/O - outputStream.write(-1) Java Basics - Anfänger-Themen 2
B Socket OutputStream Java Basics - Anfänger-Themen 17
B Socket Kommunikation in beide Richtungen Java Basics - Anfänger-Themen 12
B Socket, args Java Basics - Anfänger-Themen 22
L Socket in JTextArea Java Basics - Anfänger-Themen 9
T Input/Output Zwei InputStreams von einem Socket Java Basics - Anfänger-Themen 2
B Socket Problem Java Basics - Anfänger-Themen 3
T socket.close aber verbindung besteht noch Java Basics - Anfänger-Themen 4
F Buffered Image über Socket versenden Java Basics - Anfänger-Themen 6
E Socket InputStream "terminiert" nicht Java Basics - Anfänger-Themen 4
B Threads Interrupt während Socket.read()? Java Basics - Anfänger-Themen 3
M Versand von Nachrichten via Socket (Delay) Java Basics - Anfänger-Themen 21
F socket-problem Java Basics - Anfänger-Themen 6
E Input/Output Socket bekommt keine Verbindung bei funktionierendem Fremdziel Java Basics - Anfänger-Themen 2
E Socket (Client) dauerhaft aktiv? Java Basics - Anfänger-Themen 9
D Java - Socket - Datenübertragung Java Basics - Anfänger-Themen 18
E Input/Output einfachen Socket für XML-Anfragen bauen Java Basics - Anfänger-Themen 13
R Cannot find a free socket for the debugger Java Basics - Anfänger-Themen 6
F Socket Kommunikation Java Basics - Anfänger-Themen 4
M "Connection reset" gbxRemote Socket Java Basics - Anfänger-Themen 9
N Files mit Byte an Socket versenden Java Basics - Anfänger-Themen 2
L FTP per Socket Java Basics - Anfänger-Themen 2
J Socket - BufferedReader lese Problem Java Basics - Anfänger-Themen 2
M Socket Server Java Basics - Anfänger-Themen 9
N Socket Problem? Java Basics - Anfänger-Themen 9
G Socket erstellen dauert sehr lange. Java Basics - Anfänger-Themen 4
H Java Socket Java Basics - Anfänger-Themen 14
A XML Daten über Socket Java Basics - Anfänger-Themen 3
I Allgemeine fragen zu Socket server Java Basics - Anfänger-Themen 6
C Socket Programmierung Java Java Basics - Anfänger-Themen 4
F Socket Instanz auf Klasse welche von Socket erbt zuweisen Java Basics - Anfänger-Themen 3
ven000m Wieso antwortet mein Server nicht mehr (Socket Anwendung) Java Basics - Anfänger-Themen 2
J Daten von einem (char*)Socket einlesen. Java Basics - Anfänger-Themen 3
S Java Socket Java Basics - Anfänger-Themen 3
K Frage zu SdtOut streams bzw. Socket Programmierung Java Basics - Anfänger-Themen 3
M HTTP-Anfragen und Socket Java Basics - Anfänger-Themen 2
M Ändern einer Socket-Eigenscheft aus einem modalen Dialog? Java Basics - Anfänger-Themen 6
LimDul Suche Java Stream Tutorial Java Basics - Anfänger-Themen 2
W Stream und LocalDate Java Basics - Anfänger-Themen 15
M Stream mit den ersten n natürlichen Zahlen Java Basics - Anfänger-Themen 4
berserkerdq2 Wo ist der SInn, dass man den Stream, den ich zum Schreiben nutze, outputstream nenne? Java Basics - Anfänger-Themen 5
berserkerdq2 Wann soll ich den Stream schließen, wenn ich das in einer Methode habe? Java Basics - Anfänger-Themen 8
K Erste Schritte Stream-Aufruf vereinfachen Java Basics - Anfänger-Themen 3
I Datei als Stream aus Ressource laden? Java Basics - Anfänger-Themen 2
O Alternative zu Stream.forEach() Java Basics - Anfänger-Themen 6
Dimax stream in string[] speichern Java Basics - Anfänger-Themen 6
S Java Stream API Java Basics - Anfänger-Themen 6
A Stream Java Basics - Anfänger-Themen 14
N String N-Gramme mit Stream erstellen Java Basics - Anfänger-Themen 7
T Buffered Stream leert Txt File Java Basics - Anfänger-Themen 3
A Textdatei mit stream einlesen Java Basics - Anfänger-Themen 2
B Text-Datei nur in Stream speichern und dann ausgeben Java Basics - Anfänger-Themen 3
J Gefilterten Stream über die Konsole ausgeben Java Basics - Anfänger-Themen 1
J Count und Copy in Stream<Path> Java Basics - Anfänger-Themen 11
W for Schleife in allgemeingültiges Konstrukt aus Stream und Lambdas Java Basics - Anfänger-Themen 6
W Stream Array List - Frage Java Basics - Anfänger-Themen 5
G refactoring mit stream Java Basics - Anfänger-Themen 27
P Java Verketten von Stream - Bedeutung der Anweisungen? Java Basics - Anfänger-Themen 3
nightsky_ Methoden (Stream) Collectors.toMap() Java Basics - Anfänger-Themen 2
W HTTP-Stream auf Ajax umbauen Java Basics - Anfänger-Themen 7
elischa Client-Server IO und Stream Steuerung ? Java Basics - Anfänger-Themen 2
N Eigene Stream Methoden implementieren Java Basics - Anfänger-Themen 3
M Panel erstellen, welches ein Control erhält. Ausgabe soll über einen Stream erfolgen. Java Basics - Anfänger-Themen 0
E Stream closed - Obwohl nicht manuell geschlossen! Java Basics - Anfänger-Themen 0
N Java.io.ioexception: Stream closed Java Basics - Anfänger-Themen 2
P Wann Byte-Stream und wann Character-Stream? Java Basics - Anfänger-Themen 11
S Input/Output nullpointerException beim schliessen von stream Java Basics - Anfänger-Themen 3
A Integer aus Stream to Double Java Basics - Anfänger-Themen 7
P Java Stream, wann welche Stream verwenden? Java Basics - Anfänger-Themen 3
M Java Stream?! Java Basics - Anfänger-Themen 8
S Input/Output Data-Input/Output-Stream Java Basics - Anfänger-Themen 2
V Jar-Datei von Byte-Array oder Stream laden? Java Basics - Anfänger-Themen 9
J Input/Output Auf effiziente Weise einen Stream auszulesen Java Basics - Anfänger-Themen 5
M Stream close Java Basics - Anfänger-Themen 6
A Prüfen ob Datei geöffnet ist bzw Stream finden Java Basics - Anfänger-Themen 2
H exception "java.io.IOException: Stream closed" Java Basics - Anfänger-Themen 10
Burny91 File.delete(file) geht nicht-Offener Stream aber WO? Java Basics - Anfänger-Themen 4
H Fehler-Stream grafisch umsetzen Java Basics - Anfänger-Themen 4
H Datentypen Byte-Array aus Stream lesen Java Basics - Anfänger-Themen 3
S Fehler beim Speichern von MP3-Stream Java Basics - Anfänger-Themen 6
bambi0815 Text Datei Stream to Char[][] Java Basics - Anfänger-Themen 7
D JSP: IOException: Stream closed nach dispatchter.forward(..) Java Basics - Anfänger-Themen 13
G Warum bei Stream close() aufrufen. Java Basics - Anfänger-Themen 12
G NoClassDefFoundError: javax/xml/stream/XMLStreamException Java Basics - Anfänger-Themen 23
P Stream Java Basics - Anfänger-Themen 4
alexpetri javax.xml.stream.* nicht gefunden Java Basics - Anfänger-Themen 3
M Stream unvollständig Java Basics - Anfänger-Themen 5
Zed Stream in Variable speichern. Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben