1. 程式人生 > >【網路】JAVA Socket 實現HTTP與HTTPS客戶端傳送POST與GET方式請求

【網路】JAVA Socket 實現HTTP與HTTPS客戶端傳送POST與GET方式請求

JAVA Socket 實現HTTP與HTTPS客戶端傳送POST與GET方式請求

哇,一看標題怎麼這麼長啊,其實意思很簡單,哥討厭用HTTP Client做POST與GET提交

覺得那個畢竟是別人寫得API庫,所以我就自己實現了一個簡單的HTTP客戶端,支援POST

方式提交資料,GET方式查詢資料,是測試Restful API比較方便點,然後支援form與JSON兩

種方式提交資料,當然也支援返回資料為JSON格式.當然這些東西都是基於JAVA Socket直

接完成的,不借助任何第三方的庫,主要是JDK的API其實已經夠用啦. 當然我也沒有用

URLConnect這個東西,畢竟它在Socket基礎上又包裝了一下,有違我寫這篇文章的目的.

好啦,講完理由,下面就說說要怎麼樣才能實現啊,光說不練假把式啊!大致分了幾個步驟

一:當然是要知道HTTP協議,知道常用的HTTP請求頭,比如Host, Accept, Content-Type

    知道HTTP協議支援的方法,常用有GET/POST/PUT/DELETE等

    如果不知道,也不用擔心,我保證你讀完這篇文章,你就知道一些啦,當然有個最好的參考

    文件就是HTTP相關的RFC文件,認真讀一下肯定解決你自己心中的HTTP那些疑惑

二: 知道傳送HTTP GET與POST格式很重要, 固定的格式如下:

    [REQUEST]<SP><URL><SP>[HTTP VERSION]<CLRF>

    [REQUEST HEADER: ]<SP>[VALUE]<CLRF>

    可以有多個請求頭

    最後<CLRF>

    傳送完HTTP請求頭部以後, 針對不同請求如POST要傳送內容部分,傳送完成以後同樣

    以<CLRF>結尾.

    解釋: <SP>表示空格, <CLRF>表示回車換行JAVA中表示為”\r\n”

    REQUEST表示HTTP請求命令,可以為POST, GET, PUT, DELETE等之一

    HTTP VERSION的常見可能值為HTTP/1.1或者HTTP/1.0

三: 如果1與2的知識你都具備了,下面就來介紹一下JAVA Socket的相關知識

    如何建立一個JAVA客戶端套接字Socket s = new Socket()如此即可,簡單吧!

    如何連線到遠端的主機與埠, 當提供URL字串時候,可以這麼做

   URL url = new URL(“http://blog.csdn.net/jia20003”);

   String host = url.getHost;

   int port = url.getDefaultPort();

SocketAddress dest = new InetSocketAddress(this.host, this.port);

   s.connect(dest);

   即可連線到遠端主機,下面就可以請求文章內容了, 也很容易的

[java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. String path = "/jia20003/article/details/16908661";  
  2. SocketAddress dest = new InetSocketAddress(this.host, this.port);  
  3. socket.connect(dest);  
  4. OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());  
  5. bufferedWriter = new BufferedWriter(streamWriter);  
  6. bufferedWriter.write("GET " + path + " HTTP/1.1\r\n");  
  7. bufferedWriter.write("Host: " + this.host + "\r\n");  
  8. bufferedWriter.write("\r\n");  
  9. bufferedWriter.flush();  
String path = "/jia20003/article/details/16908661";
SocketAddress dest = new InetSocketAddress(this.host, this.port);
socket.connect(dest);
OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());
bufferedWriter = new BufferedWriter(streamWriter);
bufferedWriter.write("GET " + path + " HTTP/1.1\r\n");
bufferedWriter.write("Host: " + this.host + "\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.flush();

最後也是最重要的一點,字元編碼,儘量都用同一種字元編碼來發

送請求資料,推薦使用utf-8測試程式, 我寫兩個簡單的PHP檔案放

在wamp server上,完成對全部程式碼的測試

四:關於HTTP與HTTPS

HTTP協議是位於第四層協議TCP之上完成的應用層協議, 端到端都是明文傳送,別人一

旦網路抓包以後都可以看到你的提交與請求資料,這個好像不太安全. HTTP協議的預設

是80這個是RFC文件宣告的,屬於官方標準,沒什麼道理可以講.

HTTPS是基於SSL加密傳輸的,這樣別人截獲你的資料包破解的概率要小一點,比HTTP安

全一點,其預設埠是443, 好像QQ郵箱與谷歌的WEB Mail郵箱都是基於HTTPS. 但是

HTTPS通訊方式只是傳輸資料加密,都客戶端來說是透明的,它還是一樣要遵守HTTP協

議規範來發送POST與GET請求等.

完整的測試程式如下:

[java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. package com.gloomyfish.http.client;  
  2. import java.io.BufferedInputStream;  
  3. import java.io.BufferedReader;  
  4. import java.io.BufferedWriter;  
  5. import java.io.IOException;  
  6. import java.io.InputStreamReader;  
  7. import java.io.OutputStreamWriter;  
  8. import java.net.InetSocketAddress;  
  9. import java.net.Socket;  
  10. import java.net.SocketAddress;  
  11. import java.net.URLEncoder;  
  12. publicclass TestDemo {  
  13.     privateint port;  
  14.     private String host;  
  15.     private Socket socket;  
  16.     private BufferedReader bufferedReader;  
  17.     private BufferedWriter bufferedWriter;  
  18.     public TestDemo(String host, int port) {  
  19.         socket = new Socket();  
  20.         this.host = host;  
  21.         this.port = port;  
  22.     }  
  23.     publicvoid sendGet() throws IOException  
  24.     {  
  25.         String path = "/zhigang/getDemo.php";  
  26.         SocketAddress dest = new InetSocketAddress(this.host, this.port);  
  27.         socket.connect(dest);  
  28.         OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());  
  29.         bufferedWriter = new BufferedWriter(streamWriter);  
  30.         bufferedWriter.write("GET " + path + " HTTP/1.1\r\n");  
  31.         bufferedWriter.write("Host: " + this.host + "\r\n");  
  32.         bufferedWriter.write("\r\n");  
  33.         bufferedWriter.flush();  
  34.         BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());  
  35.         bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8"));  
  36.         String line = null;  
  37.         while((line = bufferedReader.readLine())!= null)  
  38.         {  
  39.             System.out.println(line);  
  40.         }  
  41.         bufferedReader.close();  
  42.         bufferedWriter.close();  
  43.         socket.close();  
  44.     }  
  45.     publicvoid sendPost() throws IOException  
  46.     {  
  47.         String path = "/zhigang/postDemo.php";  
  48.         String data = URLEncoder.encode("name""utf-8") + "=" + URLEncoder.encode("gloomyfish""utf-8") + "&" +  
  49.                         URLEncoder.encode("age""utf-8") + "=" + URLEncoder.encode("32""utf-8");  
  50.         // String data = "name=zhigang_jia";
  51.         SocketAddress dest = new InetSocketAddress(this.host, this.port);  
  52.         socket.connect(dest);  
  53.         OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), "utf-8");  
  54.         bufferedWriter = new BufferedWriter(streamWriter);  
  55.         bufferedWriter.write("POST " + path + " HTTP/1.1\r\n");  
  56.         bufferedWriter.write("Host: " + this.host + "\r\n");  
  57.         bufferedWriter.write("Content-Length: " + data.length() + "\r\n");  
  58.         bufferedWriter.write("Content-Type: application/x-www-form-urlencoded\r\n");  
  59.         bufferedWriter.write("\r\n");  
  60.         bufferedWriter.write(data);  
  61.         bufferedWriter.flush();  
  62.         bufferedWriter.write("\r\n");  
  63.         bufferedWriter.flush();  
  64.         BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());  
  65.         bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8"));  
  66.         String line = null;  
  67.         while((line = bufferedReader.readLine())!= null)  
  68.         {  
  69.             System.out.println(line);  
  70.         }  
  71.         bufferedReader.close();  
  72.         bufferedWriter.close();  
  73.         socket.close();  
  74.     }  
  75.     publicstaticvoid main(String[] args)  
  76.     {  
  77.         TestDemo td = new TestDemo("127.0.0.1",8099);  
  78.         try {  
  79.             // td.sendGet(); //send HTTP GET Request
  80.             td.sendPost(); // send HTTP POST Request
  81.         } catch (IOException e) {  
  82.             // TODO Auto-generated catch block
  83.             e.printStackTrace();  
  84.         }  
  85.     }  
  86. <span style="font-size: 18px;">}</span>  
package com.gloomyfish.http.client;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URLEncoder;

public class TestDemo {
	private int port;
	private String host;
	private Socket socket;
	private BufferedReader bufferedReader;
	private BufferedWriter bufferedWriter;
	public TestDemo(String host, int port) {
		socket = new Socket();
		this.host = host;
		this.port = port;
	}
	
	public void sendGet() throws IOException
	{
		String path = "/zhigang/getDemo.php";
		SocketAddress dest = new InetSocketAddress(this.host, this.port);
		socket.connect(dest);
		OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());
		bufferedWriter = new BufferedWriter(streamWriter);
		
		bufferedWriter.write("GET " + path + " HTTP/1.1\r\n");
		bufferedWriter.write("Host: " + this.host + "\r\n");
		bufferedWriter.write("\r\n");
		bufferedWriter.flush();
		
		BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());
		bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8"));
		String line = null;
		while((line = bufferedReader.readLine())!= null)
		{
			System.out.println(line);
		}
		bufferedReader.close();
		bufferedWriter.close();
		socket.close();
	}
	
	public void sendPost() throws IOException
	{
		String path = "/zhigang/postDemo.php";
		String data = URLEncoder.encode("name", "utf-8") + "=" + URLEncoder.encode("gloomyfish", "utf-8") + "&" +
						URLEncoder.encode("age", "utf-8") + "=" + URLEncoder.encode("32", "utf-8");
		// String data = "name=zhigang_jia";
		SocketAddress dest = new InetSocketAddress(this.host, this.port);
		socket.connect(dest);
		OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), "utf-8");
		bufferedWriter = new BufferedWriter(streamWriter);
		
		bufferedWriter.write("POST " + path + " HTTP/1.1\r\n");
		bufferedWriter.write("Host: " + this.host + "\r\n");
		bufferedWriter.write("Content-Length: " + data.length() + "\r\n");
		bufferedWriter.write("Content-Type: application/x-www-form-urlencoded\r\n");
		bufferedWriter.write("\r\n");
		bufferedWriter.write(data);
		bufferedWriter.flush();
		bufferedWriter.write("\r\n");
		bufferedWriter.flush();
		
		BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());
		bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8"));
		String line = null;
		while((line = bufferedReader.readLine())!= null)
		{
			System.out.println(line);
		}
		bufferedReader.close();
		bufferedWriter.close();
		socket.close();
	}
	
	public static void main(String[] args)
	{
		TestDemo td = new TestDemo("127.0.0.1",8099);
		try {
			// td.sendGet(); //send HTTP GET Request
			
			td.sendPost(); // send HTTP POST Request
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

<span style="font-size:18px;">}</span>

想要成為支援HTTPS客戶端, 只要在建立Socket的時候如下:

[java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. <span style="font-size: 18px;">socket = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(this.host, port);</span>  
<span style="font-size:18px;">socket = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(this.host, port);</span>

所以有時候離開apache的HTTP Client等第三方Jar,程式設計師也是一樣活!