2016-09-03 5 views
1

ich einen Server schreibe, die HTTP-Anforderung empfängt (nur Methode GET als von der Schule Arbeit Teil der Vereinfachung)Warum scanner.hasNext() blockiert beim Lesen Http Anfrage

I Socket Klasse verwendet, um die Verbindung ich dann zu bekommen verwendet InputStream sowie Scanner, um die HTTP-Anfrage zu lesen.

Allerdings, während ich die HTTP-Anfrage Header Zeile für Zeile mit hasNext() lesen. Das Programm hängt bei hasNext() und wartet auf weitere Eingaben, selbst wenn es alle Zeilen verbraucht hat.

Unten ist mein readRequest Methode:

public void readRequest(Socket client) throws BadRequestException { 
    StringBuilder builder = new StringBuilder(); 

    try { 
     Scanner sc = new Scanner(client.getInputStream()); 
     sc.useDelimiter("\\r\\n"); 

     while(sc.hasNext()){ 
      builder.append(sc.next()); 
      builder.append("\n"); 
     } 

     parseRequestFromClient(builder.toString()); 
    } catch (IOException e) { 
     throw new BadRequestException(e.getMessage()); 
    } 
+1

Haben Sie Debugging versucht? – xenteros

+0

Sind Sie sicher, dass Sie etwas in Ihrer Schleife lesen? Ich sehe keinen Teil, der tatsächlich Header zum Server sendet, über welche Art von Anfrage es ist (ist es GET oder vielleicht etwas anderes, welche Ressource genau wollen Sie vom Server bekommen). Ohne diesen Header Server kann einfach warten und Sie nichts senden, die 'hasNext()' enthalten kann. – Pshemo

+0

@xenteros Ja, ich habe Eclipse zum Debuggen verwendet. Und es bleibt bei dieser 'while (sc.hasNext()) Zeile stehen. –

Antwort

0

Ihr dieses Problem konfrontiert, weil hasNext hinter der Szene wird die Quelle zu überprüfen, ob es eine andere passende Token, bis die Quelle sein Ende erreicht lesen -1 durch Rücksendung der ist hier nicht dein Fall.

Als Erinnerung ist hier die Javadoc des Verfahrens hasNext:

Gibt true zurück, wenn der Scanner einen anderen Token in seinem Eingang hat. Diese Methode kann blockieren, während auf den Eingang zu scannen warten. Der Scanner führt keine Eingabe weiter.


sollten Sie vermeiden, das Rad neu zu erfinden und eine Bibliothek verwenden, die es für Sie tun, wie DavidWebb und viele andere.

+0

Danke für den Beitrag geteilt. In diesem Fall kann die Verwendung von nur sc.hasNext() mich nicht den gesamten Inhalt der HTTP-Anfrage dann verbrauchen? Für jetzt habe ich 'do { \t \t \t \t nextLine = sc.next(); \t \t \t \t builder.append (nextLine); \t \t \t \t builder.append ("\ n"); \t \t \t} while (! NextLine.equals ("")); 'um dieses Problem zu umgehen. –

+0

Sie sollten in Erwägung ziehen, stattdessen einen BufferedReader zu verwenden. Https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html –

0

Nach rfc 7230 (2616 ist veraltet) lesen Bytes aus dem Sockel.

Http Anfrage muss codiert werden mit 7-Bit usascii. Jedes Byte mit Bit 7 oder weniger als 0x20 außer 0x0a und 0x0d sollte zu 400 ungültigen Anforderungen führen.

Lesen bis 0x0d 0x0a 0x0d 0x0a Sequenz.

Danach ist die erste Zeile die durch 0x0d 0x0a getrennte Anforderungszeile, rest ist Kopfzeilen.

Teilen Sie die Anforderungszeile auf 0x20, es sollte genau 3 Teile zurückgeben. Alles andere bedeutet, dass jemand Ihren Server hackt und 400 Status sendet.

Header sollten auf ":" spleißen, was genau 2 Teile ergibt. Alles andere sendet 400 Status. Trimmen (Kopfzeile)! = Kopfzeilencode 400 Status.

Erst danach können Sie die requestline [2] und die headervalues ​​mit urldecode starten.

Doppelte Kopfzeilen? 400 Status. Doppelte Anfrageparameter? 400 Status.

Alles andere führt zu einem Server, der bekanntermaßen per Anfrageparamer und Header-Schmuggel hackbar ist.

Nur durch Interpretieren usascii 7 Bit werden Sie immun sein für utf8 Hacks 0x0a hat nur eine Darstellung in usascii 7 Bit. Aber mehrere in utf8 0x0a 0x00a 0x000a 0x0000a 0x00000a 0x00000a 0x0000000a sind gleich!

Lesen Sie rfc 7230-7235, bevor Sie programmieren! Machen Sie Ihren Server sehr schwer zu hacken.

Verwandte Themen