2011-08-25 199 views
1

我試圖使用套接字從Java客戶端發佈一些數據。它會與運行php代碼的localhost進行交流,它只是將發送給它的後續參數吐出。Http Post不發佈數據

這裏是Java客戶端:

public static void main(String[] args) throws Exception { 

     Socket socket = new Socket("localhost", 8888); 
     String reqStr = "testString"; 

     String urlParameters = URLEncoder.encode("myparam="+reqStr, "UTF-8"); 
     System.out.println("Params: " + urlParameters); 

     try { 
      Writer out = new OutputStreamWriter(socket.getOutputStream(), "UTF-8"); 
      out.write("POST /post3.php HTTP/1.1\r\n"); 
      out.write("Host: localhost:8888\r\n"); 
      out.write("Content-Length: " + Integer.toString(urlParameters.getBytes().length) + "\r\n"); 
      out.write("Content-Type: text/html\r\n\n"); 
      out.write(urlParameters); 
      out.write("\r\n"); 
      out.flush(); 

      InputStream inputstream = socket.getInputStream(); 
      InputStreamReader inputstreamreader = new InputStreamReader(inputstream); 
      BufferedReader bufferedreader = new BufferedReader(inputstreamreader); 

      String string = null; 
      while ((string = bufferedreader.readLine()) != null) { 
       System.out.println("Received " + string); 
      } 

     } catch(Exception e) { 
      e.printStackTrace(); 
     } finally { 
     socket.close(); 
     } 
} 

這是post3.php的樣子:

<?php 

$post = $_REQUEST; 

echo print_r($post, true); 
?> 

我希望看到一個數組(myparams => 「的TestString」)作爲響應。但它沒有通過發佈參數到服務器。 這裏輸出:

Received HTTP/1.1 200 OK 
Received Date: Thu, 25 Aug 2011 20:25:56 GMT 
Received Server: Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8r DAV/2 PHP/5.3.6 
Received X-Powered-By: PHP/5.3.6 
Received Content-Length: 10 
Received Content-Type: text/html 
Received 
Received Array 
Received (
Received) 

只是一個FYI,這個設置適用於GET請求。

任何想法這裏發生了什麼?

+1

只是想知道...有你不使用任何理由[了HTTPClient](http://hc.apache.org/httpcomponents-client-ga/ index.html的)? – chesles

+1

或[Resty](http://beders.github.com/Resty/Resty/Overview.html)。 –

+0

@ chesles-我正在通過SSL發送數據。 HttpClient-4的文檔對設置定製的SSLSocketFactory並不是很有幫助。所以,在我用頭部計算出用HttpClient4定製SSLSocketFactory之前,我正在試用普通套接字上的東西。 – bianca

回答

1

正如Jochen和chesles正確指出的那樣,您正在使用錯誤的Content-Type:標題 - 它的確應該是application/x-www-form-urlencoded。然而,還有其他幾個問題...

  • 最後一個標題應與標題和正文之間的空行分開。這應該是一個完整的CRLF(\r\n),在你的代碼中它只是一個新行(\n)。這是一個違反協議的行爲,我有點驚訝,你並沒有從服務器獲得400 Bad Request,儘管Apache在這方面可以相當寬容。
  • 您應該指定Connection: close以確保您不會在開放套接字中閒置,服務器會在請求完成後立即關閉連接。
  • 最終的CRLF序列不是必需的。 PHP是足夠智能的,可以自行整理,但其他服務器語言和實現可能不是...

如果您使用的任何標準化協議處於原始狀態,您應該始終以至少掃描超過the RFC

另外,請學會secure your Apache installs ...

+0

非常感謝戴夫和凱瑟斯花時間幫助我。我需要訪問第三方服務器,並要求我在發送請求時發送鍵值對中的xml請求並使用text/html Content-Type。感謝您澄清我的理解。 – bianca

0

它看起來像你試圖以application/x-www-form-urlencoded格式發送數據,但是你將Content-Type設置爲text/html。

+0

如何在Content-Type文本/ html中發送數據?任何指針? – bianca

+0

@bianca通過發送一些HTML到服務器...但你爲什麼要這樣做? – DaveRandom

+0

@dave,實際的服務器接受text/html Content-Type。有沒有辦法以text/html的方式發送數據,而不是application/x-www-form-urlencoded? – bianca

0

使用

out.write("Content-Type: application/x-www-form-urlencoded\n\n"); 

代替。作爲this page狀態:

,因爲他們知道什麼樣的網絡服務器數據的多少字節期望,並通過MIME類型識別出的內容長度和Content-Type標頭是關鍵。

用於發送表格數據,即格式爲key=value&key2=value2的數據使用application/x-www-form-urlencodedvalue是否包含HTML,XML或其他數據無關緊要;服務器會爲您解釋它,您將能夠像往常一樣在PHP端的$_POST$_REQUEST陣列中檢索數據。

或者,您也可以通過讀取特殊文件php://input發送您的數據作爲原始的HTML,XML等使用適當的Content-Type頭,但你必須要retrieve the data manually in PHP

<?php 
echo file_get_contents("php://input"); 
?> 

順便說一句,如果你使用這個用於任何足夠複雜的事情,我強烈建議使用一個HTTP客戶端庫,如HTTPClient

+0

我的示例代碼適用於此更改,但實際服務器支持text/html Content-Type。有沒有辦法以text/html的方式發送數據,而不是application/x-www-form-urlencoded? – bianca

+0

@bianca你究竟想要發送給服務器?爲什麼你需要發送HTML到服務器?正在嘗試上傳文件? – DaveRandom

+0

@dave,我想將XML發送到服務器。就像這樣:testXml = <?xml version =「1.0」encoding =「UTF-8」?> testData – bianca