Web伺服器的原理
學號:201631062509
姓名:楊菓
一 、Web伺服器的實現
新建三個類:WebSever,Request,Response,並分別寫下下列程式碼。
1.WebServer.java檔案
2 3 import java.io.*; 4 import java.net.*; 5 6 public class WebServer { 7 8 /** 9 * web伺服器:實現200和404操作 10 * 原理: 11 * 伺服器監聽一個埠,並讀取瀏覽器的請求資訊,從該資訊提取出訪問的資源(這裡為檔名)。並在工作目錄下查詢是否有該資源,有則輸出資源內容,否則返回404 12 * 測試方法: 13 * 1、用String path=System.getProperty("user.dir");獲取當前的工作目錄,並在該目錄下放要測試的檔案 14 * 2、訪問127.0.0.1:8080/test.html 15 */ 16 public static void main(String[] args) { 17 // TODO Auto-generated method stub 18 ServerSocket server = null; 19 Socket s=null; 20 try 21 { 22 server=new ServerSocket(8080,3,InetAddress.getByName("127.0.0.1")); 23 }catch(Exception e) 24 { 25 e.printStackTrace(); 26 } 27 while(true) 28 { 29 try{ 30 s=server.accept(); 31 OutputStream output=s.getOutputStream(); 32 InputStream input=s.getInputStream(); 33 34 //接收請求資訊 35 Request request=new Request(input); 36 String filename=request.getUri(); 37 //System.out.println(filename); 38 39 //處理並響應請求資訊 40 Response response=new Response(output,filename); 41 response.response(); 42 43 }catch(Exception e) 44 { 45 e.printStackTrace(); 46 } 47 } 48 } 49 50 }
2.Request.java
2 import java.io.*; 3 public class Request { 4 /* 5 * 接收請求的資訊,並返回資源(檔名) 6 * */ 7 InputStream input; 8 public Request(InputStream input) 9 { 10 this.input=input; 11 } 12 public String getUri() throws IOException 13 { 14 String content=null,str=null; 15 StringBuffer request = new StringBuffer(); 16 byte[] buffer = new byte[2048]; 17 int i = 0; 18 19 try { 20 i = input.read(buffer); //讀取內容並存入buffer陣列中,並返回讀取的的位元組數。 21 } catch (IOException e) { 22 e.printStackTrace(); 23 i = -1; 24 } 25 //將buffer陣列轉換為字串 26 for(int k = 0; k < i; k++) { 27 request.append((char)buffer[k]); 28 } 29 content=request.toString(); 30 /* 31 *以下方法錯誤!用該返回會使瀏覽器不斷處於請求連線狀態 32 * BufferedReader br=new BufferedReader(new InputStreamReader(input)); 33 while((str=br.readLine())!=null) 34 { 35 content=content+str+"\r\n"; 36 } 37 */ 38 if(content!=null) 39 return getFilename(content); 40 else return null; 41 } 42 /*提取檔名*/ 43 public String getFilename(String content) 44 { 45 int a,b; 46 a=content.indexOf(' '); 47 if(a!=-1) 48 { 49 b=content.indexOf('?',a+1); 50 if(b==-1)b=content.indexOf(' ',a+1); 51 return content.substring(a+2,b); 52 } 53 return null; 54 } 55 }
3.Response.java
2 3 import java.io.*; 4 import java.io.File; 5 import java.io.IOException; 6 import java.io.OutputStream; 7 8 public class Response { 9 /** 10 * 響應並處理請求資訊 11 */ 12 public OutputStream output; 13 public String filename; 14 private static final int BUFFER_SIZE = 1024; 15 public Response(OutputStream output,String filename) 16 { 17 this.output=output; 18 this.filename=filename; 19 } 20 public void response() throws IOException 21 { 22 String path=System.getProperty("user.dir");//獲取當前的工作目錄 23 byte[] buffer = new byte[BUFFER_SIZE]; 24 int ch; 25 FileInputStream fis = null; 26 //System.out.println(path+File.separator+filename); 27 if(path!=null&&filename!=null) 28 { 29 File file=new File(path,filename); 30 String str=""; 31 /*必須新增響應頭,否則無法以html格式顯示內容*/ 32 if(file.exists()) 33 { 34 fis = new FileInputStream(file); 35 str = "HTTP/1.1 200 OK \r\n" + 36 "Content-Type: text/html\r\n" + 37 "\r\n" ; 38 output.write(str.getBytes()); 39 ch = fis.read(buffer); 40 while(ch != -1) { 41 output.write(buffer, 0, ch); 42 ch = fis.read(buffer, 0, BUFFER_SIZE); 43 } 44 } 45 else 46 { 47 str = "HTTP/1.1 404 File Not Found \r\n" + 48 "Content-Type: text/html\r\n" + 49 "Content-Length: 100\r\n" + 50 "\r\n" + 51 "<h1>404 File Not Found!</h1>"; 52 output.write(str.getBytes()); 53 } 54 } 55 output.close(); 56 } 57 }
新建一個HTML檔案,並寫下如下程式碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HELLO</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
執行結果
輸入正確地址
輸入不正確地址
二、 Web伺服器原理
1.Web伺服器工作原理圖解
首先我們暫時不考慮HTTP協議的各種請求方式,我們先跟著這張圖,將一次Web服務的工作流程過一遍,我們假設以瀏覽器作為客戶端
(1) 使用者做出了一個操作,可以是填寫網址敲回車,可以是點選連結,可以是點選按鍵等,接著瀏覽器獲取了該事件。
(2) 瀏覽器與對端服務程式建立TCP連線。
(3) 瀏覽器將使用者的事件按照HTTP協議格式**打包成一個資料包,其實質就是在待傳送緩衝區中的一段有著HTTP協議格式的位元組流。
(4) 瀏覽器確認對端可寫,並將該資料包推入Internet,該包經過網路最終遞交到對端服務程式。
(5) 服務端程式拿到該資料包後,同樣以HTTP協議格式解包,然後解析客戶端的意圖。
(6) 得知客戶端意圖後,進行分類處理,或是提供某種檔案、或是處理資料。
(7) 將結果裝入緩衝區,或是HTML檔案、或是一張圖片等。
(8) 按照HTTP協議格式將(7)中的資料打包
(9) 伺服器確認對端可寫,並將該資料包推入Internet,該包經過網路最終遞交到客戶端。
(10) 瀏覽器拿到包後,以HTTP協議格式解包,然後解析資料,假設是HTML檔案。
(11) 瀏覽器將HTML檔案展示在頁面
以上為Web伺服器工作基本原理。其實不難發現,這僅僅只是一個簡單的網路通訊。我們應該深信,作為一個伺服器,其根本的工作無非有三個
(1) 使用者做出了一個操作,可以是填寫網址敲回車,可以是點選連結,可以是點選按鍵等,接著瀏覽器獲取了該事件。
(2) 瀏覽器與對端服務程式建立TCP連線。
(3) 瀏覽器將使用者的事件按照HTTP協議格式**打包成一個資料包,其實質就是在待傳送緩衝區中的一段有著HTTP協議格式的位元組流。
(4) 瀏覽器確認對端可寫,並將該資料包推入Internet,該包經過網路最終遞交到對端服務程式。
(5) 服務端程式拿到該資料包後,同樣以HTTP協議格式解包,然後解析客戶端的意圖。
(6) 得知客戶端意圖後,進行分類處理,或是提供某種檔案、或是處理資料。
(7) 將結果裝入緩衝區,或是HTML檔案、或是一張圖片等。
(8) 按照HTTP協議格式將(7)中的資料打包
(9) 伺服器確認對端可寫,並將該資料包推入Internet,該包經過網路最終遞交到客戶端。
(10) 瀏覽器拿到包後,以HTTP協議格式解包,然後解析資料,假設是HTML檔案。
(11) 瀏覽器將HTML檔案展示在頁面
以上為Web伺服器工作基本原理。其實不難發現,這僅僅只是一個簡單的網路通訊。我們應該深信,作為一個伺服器,其根本的工作無非有三個
1. 接收資料 2. 傳送資料 3. 資料處理
而Web伺服器的本質就是 接收資料 ⇒ HTTP解析 ⇒ 邏輯處理 ⇒ HTTP封包 ⇒ 傳送資料
高階的伺服器無非就是將這三個部分更加細緻的設計了。
而Web伺服器的本質就是 接收資料 ⇒ HTTP解析 ⇒ 邏輯處理 ⇒ HTTP封包 ⇒ 傳送資料
高階的伺服器無非就是將這三個部分更加細緻的設計了。
2.Web伺服器之提供靜態檔案工作原理圖解
Web伺服器最主要的功能是提供靜態的檔案。日常的上網瀏覽大多是網頁瀏覽,少數時候才會有一些資料的提交操作。因此,我們結合上一張圖示來重點講解在GET請求下的Web伺服器工作原理。
其他流程基本不變,著重在於紅色與藍色部分。
(1) 當使用者點選一個網頁連結或瀏覽器載入一些資源(css,jpg …)時產生。
(6) 服務程式解包後,確定其為GET請求,並且是對該伺服器上的某一資源的請求。首先服務程式會去確認該路徑是否存在,再確定該路徑的檔案是否可以獲取。
(7-1) 如果請求的路徑有誤,或者該資源不能被使用者獲取,則返回錯誤提示頁面。很多伺服器的錯誤頁面只有404,更專業的應該是將錯誤分類並返回對應的錯誤內碼表面。
(7-2) 如果該路徑合法且檔案可以被獲取,那麼服務程式將根據該檔案型別進行不同的裝載過程,記錄其型別作為(8)中HTTP協議中對應的返回型別,並加入響應頭。
假設以點選一個頁面連結為例,瀏覽器首先將HTML檔案請求過來,再以同樣的流程對HTML檔案中包含的資原始檔路徑進行依次請求。
(1) 當使用者點選一個網頁連結或瀏覽器載入一些資源(css,jpg …)時產生。
(6) 服務程式解包後,確定其為GET請求,並且是對該伺服器上的某一資源的請求。首先服務程式會去確認該路徑是否存在,再確定該路徑的檔案是否可以獲取。
(7-1) 如果請求的路徑有誤,或者該資源不能被使用者獲取,則返回錯誤提示頁面。很多伺服器的錯誤頁面只有404,更專業的應該是將錯誤分類並返回對應的錯誤內碼表面。
(7-2) 如果該路徑合法且檔案可以被獲取,那麼服務程式將根據該檔案型別進行不同的裝載過程,記錄其型別作為(8)中HTTP協議中對應的返回型別,並加入響應頭。
假設以點選一個頁面連結為例,瀏覽器首先將HTML檔案請求過來,再以同樣的流程對HTML檔案中包含的資原始檔路徑進行依次請求。
3.Web伺服器之資料提交工作原理圖解
僅僅只是網頁的瀏覽並不能滿足所有人的需求,客戶端與伺服器應當是有資料互動的。
即使單方面的資源請求任然是網路的主力軍。
我們應該清楚的知道,資料提交對於使用者來說有什麼作用。
(1) 資源上傳 (2) 登陸驗證 (3) API介面呼叫 (4) 遠端指令等
資料提交使得使用者的操作性有了質的飛躍,它使得HTTP短連線獲取靜態檔案的方式提升到了動態互動的層次上。該性質也催化出各式各樣的程式語言、框架。例如PHP,JavaWeb。
如果你留意目前主流的那些大型伺服器,你會發現再高階再牛逼的東西實際是也是最基礎的東西建造的。那麼我們還可以順便學習一下最古老的動態技術CGI
其他流程基本不變,著重在於紅色與藍色部分。
(1) 使用者提交資料,假設使用者點選一個按鍵提交填好的資訊。在(3)中將以POST格式寫入,並填入提交至服務端的可執行程式的路徑。
(6) 服務端將引數與該CGI繫結,複製程式,用管道傳遞引數和接收結果
(7) 子程式執行CGI,接收(6)父程式傳來的引數,運算完成返回結果。
最後父程式將結果裝入靜態模板檔案,放入緩衝區
4.動態技術
我們得明白,Web伺服器是以短連線為主,並且獲取的資料到達瀏覽器的那一刻一定是靜態的不變的。那麼所謂動態實際是指兩種情況
(1) 使用者提交資料,假設使用者點選一個按鍵提交填好的資訊。在(3)中將以POST格式寫入,並填入提交至服務端的可執行程式的路徑。
(6) 服務端將引數與該CGI繫結,複製程式,用管道傳遞引數和接收結果
(7) 子程式執行CGI,接收(6)父程式傳來的引數,運算完成返回結果。
最後父程式將結果裝入靜態模板檔案,放入緩衝區
4.動態技術
我們得明白,Web伺服器是以短連線為主,並且獲取的資料到達瀏覽器的那一刻一定是靜態的不變的。那麼所謂動態實際是指兩種情況
服務端產生:
(1) 使用者POST提交資料到某個程式,程式根據該資料作為引數執行,得出結果並裝入靜態的模板頁面中,返回該靜態頁面。但對於使用者來說,同一個頁面,做了一個操作後資料不一樣了。好了,這就是動態頁面。(CGI原理)
(2) PHP的原理是,使用者GET請求一個php字尾的檔案,伺服器先執行該php字尾檔案中的PHP程式碼,將結果填入程式碼的位置,再返回。當然也可以提交資料參與運算再返回。
客戶端產生:
(1) 使用者GET請求一個JavaScript檔案,服務端不做任何運算返回該靜態檔案。瀏覽器收到該JS檔案,在本地執行並更新頁面。
(2) 使用者POST提交資料到服務端,服務端根據該提交的資料指令返回靜態檔案,瀏覽器收到後執行並更新。
(1) 使用者POST提交資料到某個程式,程式根據該資料作為引數執行,得出結果並裝入靜態的模板頁面中,返回該靜態頁面。但對於使用者來說,同一個頁面,做了一個操作後資料不一樣了。好了,這就是動態頁面。(CGI原理)
(2) PHP的原理是,使用者GET請求一個php字尾的檔案,伺服器先執行該php字尾檔案中的PHP程式碼,將結果填入程式碼的位置,再返回。當然也可以提交資料參與運算再返回。
客戶端產生:
(1) 使用者GET請求一個JavaScript檔案,服務端不做任何運算返回該靜態檔案。瀏覽器收到該JS檔案,在本地執行並更新頁面。
(2) 使用者POST提交資料到服務端,服務端根據該提交的資料指令返回靜態檔案,瀏覽器收到後執行並更新。