【Tomcat8.5原始碼分析】【3】一個簡單的HTTP伺服器
阿新 • • 發佈:2019-01-28
通過上面兩篇文章的學習,我們知道了HTTP\SOCK\TCP\IP之間的關係以及區別,接下來我們手寫一個HTTP伺服器
首先我們定義一個HttpServer類,該類主要用以建立一個ServerSocket,當有請求進入的時候會通過accept()方法生成一個套接字-Socket物件,然後通過Socket物件的輸入輸出流進行讀取請求資料,並返回請求結果。封裝的輸入流物件為Request,封裝的輸出流物件為Response,並且在最後如果輸入的請求裡包含./shutdown,則關閉伺服器。
程式碼如下:HttpServer類
package cn.tomcat; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * @description: * @author: gongqi * @create: 2018/11/07 15:09 */ public class HttpServer { //是否關閉伺服器 private boolean shutdown = false; //監聽的埠號 private Integer port = 9011; //資源所在的根路徑 public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot"; //停止服務的命令 private static final String SHUTDOWN_CMD = "./shutdown"; /** *啟動主類 */ public static void main(String[] args) { HttpServer server = new HttpServer(); server.await(); } /** *等待請求 */ public void await() { // ServerSocket serverSocket = null; try { //啟動一個ServerSocket並監聽對應的埠號 serverSocket = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); } //當未收到關閉命令的時候一直迴圈接受請求 while (!shutdown) { Socket socket; InputStream inputStream; OutputStream outputStream; System.out.println(WEB_ROOT); // try { //此方法是一個阻塞方法 //當有請求進來的時候會生成一個Socket物件 socket = serverSocket.accept(); //獲取輸入流 inputStream = socket.getInputStream(); //獲取輸出流 outputStream = socket.getOutputStream(); //封裝輸入流 Request request = new Request(inputStream); request.parse(); //封裝輸出流 Response response = new Response(outputStream); response.setRequest(request); response.sendStaticResource(); //關閉當次Socket連線 socket.close(); shutdown = SHUTDOWN_CMD.equals(request.getUri()); } catch (Exception e) { e.printStackTrace(); } } } }
Request類
package cn.tomcat; import java.io.IOException; import java.io.InputStream; /** * @description: * @author: gongqi * @create: 2018/11/07 16:20 */ public class Request { private InputStream input; private String uri; public Request(InputStream input) { this.input = input; } public void parse() { // StringBuffer request = new StringBuffer(2048); int i; byte[] buffer = new byte[2048]; try { //在輸入流裡讀取2048個byte,方便起見姑且先死2048吧 i = input.read(buffer); } catch (IOException e) { e.printStackTrace(); i = -1; } //迴圈byte陣列,然後一個字元一個字元的刷入StringBuffer for (int j = 0; j < i; j++) { request.append((char)buffer[j]); } //打印出請求的內容 System.out.println(request.toString()); uri = parseUri(request.toString()); } private String parseUri(String requestString) { int index1, index2; index1 = requestString.indexOf(' '); if (index1 != -1) { index2 = requestString.indexOf(' ', index1 + 1); if (index2 > index1) { return requestString.substring(index1 + 1, index2); } } return null; } public String getUri() { return uri; } }
Response類:
package cn.tomcat; import java.io.*; /** * @description: * @author: gongqi * @create: 2018/11/07 16:36 */ public class Response { private static final int BUFFER_SIZE = 1024; private Request request; private OutputStream output; public Response(OutputStream output) { this.output = output; } public void setRequest(Request request) { this.request = request; } public void sendStaticResource() throws IOException { byte[] bytes = new byte[BUFFER_SIZE]; File file = new File(HttpServer.WEB_ROOT + request.getUri()); if (file.exists()) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(file); int ch = fileInputStream.read(bytes, 0, BUFFER_SIZE); while (ch != -1) { output.write(bytes, 0, ch); ch=fileInputStream.read(bytes,0,BUFFER_SIZE); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (fileInputStream != null) { fileInputStream.close(); } } } else { String mesg = "HTTP/1.1 404 File not found\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 23\r\n" + "\r\n" + "<h1>File not found</h1>"; // try { output.write(mesg.getBytes()); } catch (IOException e) { e.printStackTrace(); } } } }
對應的HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<h1>你好哇,你成功訪問到我了!</h1>
</body>
</html>
這樣一個簡單的HTTP伺服器就寫好啦,拿去跑一下看吧,哈哈哈哈!!