从html表单读取POST数据发送到serversocket

我尝试在Java中编写最简单的服务器应用程序,显示带有textarea输入的html表单,在提交后,我可以解析在该textarea中键入的xml。 现在我构建基于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("
"); out.print("
"); out.print("
"); 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(); } }

在表单(带有xml的textarea和一个额外的文本输入)之后,在’gets’字符串类型变量中提交我的变量的Urlencoded值(也显示在屏幕上,它看起来像这样:

 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 

我该怎么做才能将GET更改为POST方法(如果我只是在表单中更改它而不是放“if(str.contains(”POST“)){”它给我字符串像

 gets = POST / HTTP/1.1 

没有变数。 之后,我如何使用我的textarea字段中的xml(称为“我们”)?

这是我读取POST主体的实现:

 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("
" + body.toString() + ""); } else { out.write("
"); out.write(""); out.write(""); out.write("
"); } // // 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()); }

我为android做了这个,在我的情况下, publishProgres意味着:

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

典型的HTTP POST请求如下所示:

 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 

第一行包含方法(通常是GET或POST,但还有更多,如HEAD,PUT,DELETE),请求URI和协议版本。 然后有许多请求标头,这对于简单的服务器可能不那么重要。 如果该方法是一个接受请求体(POST和PUT)的方法,那么在标题之后有一个空行,后跟请求体。 对于来自HTML表单的POST,正文将由所有表单元素的key=value对组成,由& 。 值将为%-encoded。

您只需要妥善解析整个请求。

您应该知道HTTP中的行结尾应该是Windows风格的( \r\n )。 readline()方法可能会将其解释为两个换行符,因此看起来每条实线之间都有一条空行。

由于标题后面有一个空行,在使用BufferedReader的readLine()方法读取标题信息之后,这是获取后有效负载数据的相对简单的方法。

 //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()) 

POST数据不在第一行。 打印所有行,你会看到。 它实际上是在空白行之后。

从这个 –

我们需要首先读取标题,然后使用标题部分中提供的实际内容长度从同一个BufferedReader中再次读取: –

 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