最簡單的web伺服器實現(一)(r4筆記第68天)
阿新 • • 發佈:2022-05-04
tomcat作為web伺服器,想必大家做過web開發的都離不開tomcat了,值得慶幸的是tomcat也是開放原始碼的,最近準備好好琢磨琢磨tomcat的原始碼,還沒開始就已經感覺到不少的未知恐懼了,慢慢來把。 可能我的學習方式比較急功近利,但是這種方式收效也快,自己記得在<<Java程式設計師 上班那點事兒>>裡作者寫過一個最簡單的web伺服器實現,自己在網上也比較了一下其它的版本,還是感覺那本書裡的版本比較好,在此分享出來,因為時間緊,照著書敲了一遍程式碼,竟然發現裡面有一些很細小的錯誤,自己準備在這個基礎上好好改進一把。 首先來看看web伺服器的一些基本原理,我們的實驗是基於socket的,開放了一個指定的埠,然後會啟用對應的執行緒來處理瀏覽器中的請求。如果檔案不存在,會報出404錯誤,否則會解析檔案的內容。 HttpServer類是後臺服務類,會開放對應的埠和socket來處理瀏覽發出的請求。 HttpThread類是接受瀏覽器傳送請求的類,通過Receive和Answer來接受和處理瀏覽器傳送的請求,然後返回到客戶端中。
package new_test; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class HttpServer { public static String ROOT="./wwwroot"; public static String defaultPage="index.html"; public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(8080); while(true){ Socket s=ss.accept(); System.out.println("Accept Connection...:"); new HttpThread(s).start(); } } } package new_test; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import } java.net.Socket; public class HttpThread extends Thread { private Socket socket; public HttpThread(Socket s) { this.socket = s; public void run() { InputStream ins = null; OutputStream ous = null; try { ous = socket.getOutputStream(); ins = socket.getInputStream(); Receive rcv = new Receive(ins); String sURL = rcv.parse(); System.out.println("sURL is " + sURL); if (sURL.equals("/")) { sURL = HttpServer.defaultPage; } Answer ans = new Answer(ous); ans.send(sURL); } catch (IOException e) { e.printStackTrace(); } finally { try { if (ins != null) { ins.close(); } if (ous != null) { ous.close(); } if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } package new_test; import java.io.IOException; import java.io.InputStream; public class Receive { InputStream in = null; public Receive(InputStream ins) { this.in = ins; } public String parse() { StringBuffer receiveStr = new StringBuffer(2048); int i ; byte[] buffer = new byte[2048]; try { i = in.read(buffer); } catch (IOException e) { i = -1; } for (int j = 0; j < i; j++) { receiveStr.append((char)buffer[j]); } return getUri(receiveStr.toString()); } private String getUri(String receiveStr) { int index1, index2; System.out.println("receiveStr is " + receiveStr); index1 = receiveStr.indexOf(" "); if (index1 != -1) { index2 = receiveStr.indexOf(" ", index1 + 1); if (index2 > index1) { return receiveStr.substring(index1 + 1, index2); } } return null; } } package new_test; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; public class Answer { OutputStream out = null; public Answer(OutputStream ous) { this.out = ous; } public void send(String pageFile) { byte[] bytes = new byte[2048]; FileInputStream fis = null; try { File file = new File(HttpServer.ROOT, pageFile); if (file.exists()) { fis = new FileInputStream(file); int ch = fis.read(bytes, 0, 2048); String sBody = new String(bytes, 0); String sendMessage = "HTTP/1.1 200 OKrn" + "Content-Type:text/htmlrn" + "Content-Length:" + ch + "rn" + "rn" + sBody; out.write(sendMessage.getBytes()); } else { String errorMessage = "Http/1.1 404 File NOT FOUNDrn" + "Content-Type:text/htmlrn" + "Content-Length:23rn" + "rn" + "<h1>File Not Found</h1>"; out.write(errorMessage.getBytes()); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
一個簡單呼叫的情況就是,如果不存在對應的頁面會直接丟擲File Not Found的錯誤資訊