2010-06-13 11 views
5

intento escribir la aplicación de servidor más simple posible en Java, mostrando el formulario html con la entrada textarea, que después de enviarlo me da la posibilidad de analizar xml escrito en ese área de texto. Por ahora construyo servidor basado ServerSocket sencillo como eso:Lectura de datos POST desde un formulario html enviado a serversocket

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(); 
    } 
} 

Después de la forma (área de texto con XML y una entrada de texto adicional) se presenta en 'consigue' variable de tipo cadena que he urlencoded valores de mi variables (también representada en la pantalla, se ve así:

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 

¿Qué puedo hacer para cambiar llegar al método POST (si simplemente lo cambio en su forma y que puse "si (str.contains (" POST ")) { "me da cadena como

gets = POST/HTTP/1.1 

sin variables. Y después de eso, ¿cómo puedo usar xml desde mi campo textarea (llamado 'nosotros')?

+0

Hola qqryq. Tengo el mismo código. ¿Has descubierto cómo leer el cuerpo POST?Intenté ejecutar el segundo ciclo mientras dice cygri, pero los métodos inputStream.read o bufferedReader.readline bloquean mi hilo. ¿Cómo lees el cuerpo POST? – Alexmelyon

+1

¡Oh, me di cuenta! Necesito leer el encabezado "Content-Length:" y hacer for-cycle a esta longitud. – Alexmelyon

Respuesta

3

Los datos POST no están en la primera línea. Imprime todas las líneas y verás. En realidad, es inmediatamente después de una línea en blanco.

+3

bien, pero ¿cómo puedo pronunciar todo si tengo 'while (! Str.equals ("")) {' declaración? Ignorar la primera línea en blanco y detenerse en otra? – qqryq

5

Una petición típica HTTP POST es así:

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 

La primera línea contiene el método (normalmente GET o POST, pero hay más, como la cabeza, PUT, DELETE), el URI de la solicitud, y el versión de protocolo. Luego hay una serie de encabezados de solicitud, que pueden no ser tan importantes para un servidor simple. Si el método es uno que toma un cuerpo de solicitud (POST y PUT), luego de los encabezados hay una línea en blanco seguida del cuerpo de la solicitud. En el caso de un POST de un formulario HTML, el cuerpo constará de key=value pares para todos los elementos de formulario, unidos por &. Los valores serán% -encoded.

Solo tiene que encargarse de analizar correctamente toda la solicitud.

Debe tener en cuenta que se supone que las terminaciones de línea en HTTP son de estilo Windows (\r\n). El método readline() podría interpretar esto como dos saltos de línea, por lo que podría parecer que hay una línea vacía entre cada una de las líneas reales.

+3

bien, pero ¿cómo llegar a esa información cuando mi tiempo se detiene en la primera línea vacía? – qqryq

+0

Reescriba su ciclo while para que no se detenga en la primera línea. ¿Necesitas ayuda con eso? – cygri

8

Esta es mi aplicación para el cuerpo Post decía:

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()); 
} 

lo hago por androide y publishProgres en mi caso significa:

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

Básicamente, la primera lectura debe recoger todas las líneas del encabezado. Después de eso, el encabezado Content-Length debe usarse para saber por adelantado cuántos caracteres se deben leer y luego simplemente avanzar para un procesamiento posterior. – prash

4

Como hay una línea en blanco después de las cabeceras, aquí es mi forma relativamente simple de obtener los datos de la carga posterior, después de haber leído la información del encabezado usando el método readLine() de 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

De this -

Tenemos que leer primero las cabeceras y luego leer de nuevo desde el mismo BufferedReader usando longitud del contenido real proporcionada en la sección de encabezado: -

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

Cuestiones relacionadas