2010-06-13 23 views
5

Staram się napisać najprostszą możliwą aplikację serwerową w Javie, wyświetlając formularz html z wejściem textarea, który po przesłaniu daje mi możliwość parsowania xml wpisanego w to pole tekstowe. Na razie mogę zbudować prosty serwer oparty ServerSocket tak:Czytanie danych POST z formularza html wysłanych na serverocket

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class WebServer { 

    protected void start() { 
    ServerSocket s; 
    String gets = ""; 
    System.out.println("Start on port 80"); 
    try { 
     // create the main server socket 
     s = new ServerSocket(80); 
    } catch (Exception e) { 
     System.out.println("Error: " + e); 
     return; 
    } 

    System.out.println("Waiting for connection"); 
    for (;;) { 
     try { 
     // wait for a connection 
     Socket remote = s.accept(); 
     // remote is now the connected socket 
     System.out.println("Connection, sending data."); 
     BufferedReader in = new BufferedReader(new InputStreamReader(
      remote.getInputStream())); 
     PrintWriter out = new PrintWriter(remote.getOutputStream()); 

     String str = "."; 

     while (!str.equals("")) { 
      str = in.readLine(); 
      if (str.contains("GET")){ 
      gets = str; 
      break; 
      } 
     } 

     out.println("HTTP/1.0 200 OK"); 
     out.println("Content-Type: text/html"); 
     out.println(""); 
     // Send the HTML page 
     String method = "get"; 
     out.print("<html><form method="+method+">"); 
     out.print("<textarea name=we></textarea></br>"); 
     out.print("<input type=text name=a><input type=submit></form></html>"); 
     out.println(gets); 
     out.flush(); 

     remote.close(); 
     } catch (Exception e) { 
     System.out.println("Error: " + e); 
     } 
    } 
    } 

    public static void main(String args[]) { 
    WebServer ws = new WebServer(); 
    ws.start(); 
    } 
} 

Po postaci (textarea z XML i jednego dodatkowego wprowadzania tekstu) jest składany w „dostaje” String-typ zmiennej Mam urlencoded wartości moich zmiennych (wyświetlany również na ekranie, wygląda na to, że:

gets = GET /?we=%3Cnetwork+ip_addr%3D%2210.0.0.0%2F8%22+save_ip%3D%22true%22%3E%0D%0A%3Csubnet+interf_used%3D%22200%22+name%3D%22lan1%22+%2F%3E%0D%0A%3Csubnet+interf_used%3D%22254%22+name%3D%22lan2%22+%2F%3E%0D%0A%3C%2Fnetwork%3E&a=fooBar HTTP/1.1 

Co mogę zrobić, aby dostać się do zmiany metody POST (jeśli ja po prostu zmienić go w formie, niż umieścić "if (str.contains (" POST ")) { "daje mi ciąg znaków takich jak:

gets = POST/HTTP/1.1 

bez zmiennych. A po tym, jak mogę użyć xml z mojego pola tekstowego (zwanego "my")?

+0

Cześć qqryq. Mam ten sam kod. Czy wymyśliłeś, jak przeczytać ciało POST?Próbowałem uruchomić drugi cykl, jak mówi cygri, ale metody inputStream.read lub bufferedReader.readline blokują mój wątek. Jak czytasz ciało POST? – Alexmelyon

+1

Och, zdałem sobie sprawę! Potrzebuję przeczytać nagłówek "Content-Length:" i zrobić dla cyklu na taką długość. – Alexmelyon

Odpowiedz

3

Dane POST nie znajdują się w pierwszym wierszu. Wydrukuj wszystkie linie, a zobaczysz. Właściwie natychmiast po pustej linii.

+3

ok, ale jak mogę pront wszystko, jeśli mam 'while (! Str.equals ("")) {' instrukcja? Zignorować pierwszą pustą linię i zatrzymać się na drugiej? – qqryq

5

Typowy żądanie POST HTTP wygląda następująco:

POST/HTTP/1.1 
Host: www.example.com 
Accept: text/html,*/*;q=0.5 
User-Agent: BrowserName/1.0 
Referer: http://www.example.com/ 
Content-type: application/x-www-form-urlencoded; charset=utf-8 

foo=1&bar=2 

Pierwszy wiersz zawiera metodę (zazwyczaj GET lub POST, ale nie więcej, jak głowa, PUT, DELETE), URI żądania, a wersja protokołu. Następnie istnieje wiele nagłówków żądań, które mogą nie być tak ważne dla prostego serwera. Jeśli metoda przyjmuje postać żądania (POST i PUT), po nagłówkach jest pusta linia, a następnie treść żądania. W przypadku POST z formularza HTML, ciało składa się z par key=value dla wszystkich elementów formularza, połączonych przez &. Wartości będą kodowane w%.

Trzeba tylko zadbać o poprawne przeanalizowanie całego żądania.

Należy pamiętać, że zakończenia linii w protokole HTTP mają być w stylu Windows (\r\n). Metoda readline() może zinterpretować to jako dwie linie podziału, więc może wyglądać na pustą linię między każdą z linii rzeczywistych.

+3

ok, ale jak dostać się do tych danych, gdy mój czas zatrzymuje się na pierwszej pustej linii? – qqryq

+0

Przepisz pętlę while, tak aby nie zatrzymywała się w pierwszym wierszu. Potrzebujesz pomocy? – cygri

8

To moja realizacja dla ciała odczytu postu:

try { 
    Socket socket = params[0]; 
    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
    // read request 
    String line; 
    line = in.readLine(); 
    StringBuilder raw = new StringBuilder(); 
    raw.append("" + line); 
    boolean isPost = line.startsWith("POST"); 
    int contentLength = 0; 
    while (!(line = in.readLine()).equals("")) { 
     raw.append('\n' + line); 
     if (isPost) { 
      final String contentHeader = "Content-Length: "; 
      if (line.startsWith(contentHeader)) { 
       contentLength = Integer.parseInt(line.substring(contentHeader.length())); 
      } 
     } 
    } 
    StringBuilder body = new StringBuilder(); 
    if (isPost) { 
     int c = 0; 
     for (int i = 0; i < contentLength; i++) { 
      c = in.read(); 
      body.append((char) c); 
      Log.d("JCD", "POST: " + ((char) c) + " " + c); 
     } 
    } 
    raw.append(body.toString()); 
    publishProgress(raw.toString()); 
    // send response 
    out.write("HTTP/1.1 200 OK\r\n"); 
    out.write("Content-Type: text/html\r\n"); 
    out.write("\r\n"); 
    out.write(new Date().toString()); 
    if (isPost) { 
     out.write("<br><u>" + body.toString() + "</u>"); 
    } else { 
     out.write("<form method='POST'>"); 
     out.write("<input name='name' type='text'/>"); 
     out.write("<input type='submit'/>"); 
     out.write("</form>"); 
    } 
    // 
    // do not in.close(); 
    out.flush(); 
    out.close(); 
    socket.close(); 
    // 
} catch (Exception e) { 
    e.printStackTrace(); 
    StringWriter sw = new StringWriter(); 
    e.printStackTrace(new PrintWriter(sw)); 
    publishProgress('\n' + sw.toString()); 
} 

robię to dla android i publishProgres w moim przypadku oznacza:

protected void onProgressUpdate(String... values) { 
     super.onProgressUpdate(values); 
     instance.logTextView.append(values[0]); 
    } 
+2

Zasadniczo, pierwszy odczyt powinien zebrać wszystkie linie nagłówka. Następnie należy użyć nagłówka Content-Length, aby wiedzieć z góry, ile znaków należy przeczytać, a następnie po prostu przejść do dalszego przetwarzania – prash

4

Ponieważ nie jest pusta linia następujące nagłówki, tutaj jest moim stosunkowo prostym sposobem na uzyskanie danych po ładunku, po przeczytaniu informacji nagłówka przy użyciu metody BufferedReader.

//socket is an instance of Socket 
InputStream is = socket.getInputStream(); 
InputStreamReader isReader = new InputStreamReader(is); 
BufferedReader br = new BufferedReader(isReader); 

//code to read and print headers 
String headerLine = null; 
    while((headerLine = br.readLine()).length() != 0){ 
     System.out.println(headerLine); 
    } 

//code to read the post payload data 
StringBuilder payload = new StringBuilder(); 
     while(br.ready()){ 
      payload.append((char) br.read()); 
      } 
System.out.println("Payload data is: "+payload.toString()) 
1

Od this -

Musimy najpierw przeczytać nagłówki, a następnie odczytać ponownie z tego samego BufferedReader stosując rzeczywistą długość treści zawartych w sekcji nagłówka: -

BufferedReader in = new BufferedReader(new InputStreamReader(is)); 
String line; 
line = in.readLine(); 
while ((line = in.readLine()) != null && (line.length() != 0)) { 
    System.out.println("HTTP-HEADER: " + line); 
    if (line.indexOf("Content-Length:") > -1) { 
    postDataI = new Integer(
     line.substring(
      line.indexOf("Content-Length:") + 16, 
      line.length())).intValue(); 
    } 
} 
String postData = ""; 
// read the post data 
if (postDataI > 0) { 
    char[] charArray = new char[postDataI]; 
    in.read(charArray, 0, postDataI); 
    postData = new String(charArray); 
} 

HTH

Powiązane problemy