一段代碼和多幅圖讓你明白http

一直以來有對http很多不明白的地方。請教了很多人,自己也做了不少的測試。在此貼上我的心得。有磚望輕拍。


源碼:

package socket;

import java.io.*;
import java.net.*;

public class MyServer {
	public static void main(String[] args) throws IOException{
		ServerSocket svrSocket = new ServerSocket(80);
		Socket socket = svrSocket.accept();
		//buffer
		byte[] buf = new byte[1024*1024];
		InputStream in = socket.getInputStream();
		//request ip
		System.out.println(socket.getInetAddress());
		
		int byteRead = in.read(buf, 0, 1024*1024);
		
		String dataString = new String(buf, 0, byteRead);
		//request
		System.out.println(dataString);

		PrintWriter p = new PrintWriter(socket.getOutputStream());
		//important  . something is different with safari
		StringBuilder sb = new StringBuilder("HTTP/2.0 200 NOT-OK\r\n")
		.append("Host: localhost\r\n")
		.append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0\r\n")
		.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n")
		.append("Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n")
		.append("Accept-Encoding: gzip, deflate\nConnection: keep-alive\r\n")
		.append("Cache-control: no-cache\r\n")
		//useful
		.append("\r\n");
		//header
		p.write(sb.toString().toCharArray());
		//body
		p.write("hello");
		p.flush();
		in.close();
		svrSocket.close();
		/*寫法有些非標準的地方*/
	}
}

這兒就使用socket啓動了一個服務器了。並且,它是可以被看做http服務器的。在瀏覽器裏面訪問:

看firbug裏面的請求和響應(分別對應了上面console裏面打印的和代碼裏面所寫的)

再看看iptool的截取

瀏覽器發送請求http請求沒有指定的話默認GET.

不難看出這是TCP請求。三次握手完畢之後瀏覽器發送請求數據。等待服務器響應。因爲是keep-alive,每隔一段時間服務器與瀏覽器相互發送確認在線信息。因此咱們需要關注的就是請求和響應的了:

最後那14忘記是幹嘛的了,但是他沒有被包含在這個http請求裏邊:


因此: http請求數據,就這些,不能再多了:

GET / HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive

下面看看服務器反饋的信息,結合着請求信息,就更加容易看明白了:

			StringBuilder sb = new StringBuilder("HTTP/2.0 200 NOT-OK\r\n")
			.append("Host: localhost\r\n")
			.append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0\r\n")
			.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n")
			.append("Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n")
			.append("Accept-Encoding: gzip, deflate\nConnection: keep-alive\r\n")
			.append("Cache-control: no-cache\r\n")
			//useful
			.append("\r\n");
			//header
			p.write(sb.toString().toCharArray());
			//body
			p.write("hello");

蘋果的safari對這部分做了重寫,這個更容易被看到:




總結:

①HTTP協議是一個應用層的協議,具體怎麼發,還得交給TCP和IP協議再遞交給物理層去發送。

②不管什麼設備,使用了HTTP協議發送就的遵循他的規範,它也會將發送者的數據封裝成HTTP請求再來發送至於加密(https)或者是保持鏈接(keep-alive)等,又是在它的特性或者是在它上面做了修改了的。

③向一個設備發送一個HTTP請求,只要對方支持HTTP則這個連接就是HTTP連接,它滿足HTTP的各項特性。哪怕是對方回饋的數據並沒交由HTTP封裝工具(常用的tomcat或者apache或者IIS,封裝成標準的HTTP報文)去封裝而是對方自己封裝的(剛剛我做的封裝,電腦firefox能讀出,安卓UC能讀出,蘋果safari就是讀不出),這個回饋還是HTTP RESPONSE。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章