一個簡單的Java web伺服器實現

来源:http://www.cnblogs.com/chenpi/archive/2016/06/20/5602171.html
-Advertisement-
Play Games

一個簡單的Java web伺服器實現,比較簡單,基於java.net.Socket和java.net.ServerSocket實現; 程式執行步驟 代碼實現 伺服器實現: Request類: Response類: 結果測試 訪問存在的資源文件(註意存放在工程目錄的webroot文件夾里): 訪問不存 ...


  一個簡單的Java web伺服器實現,比較簡單,基於java.net.Socket和java.net.ServerSocket實現;

程式執行步驟

  1. 創建一個ServerSocket對象;
  2. 調用ServerSocket對象的accept方法,等待連接,連接成功會返回一個Socket對象,否則一直阻塞等待;
  3. Socket對象中獲取InputStream和OutputStream位元組流,這兩個流分別對應request請求和response響應;
  4. 處理請求:讀取InputStream位元組流信息,轉成字元串形式,並解析,這裡的解析比較簡單,僅僅獲取uri(統一資源標識符)信息;
  5. 處理響應:根據解析出來的uri信息,從WEB_ROOT目錄中尋找請求的資源資源文件, 讀取資源文件,並將其寫入到OutputStream位元組流中;
  6. 關閉Socket對象;
  7. 轉到步驟2,繼續等待連接請求;

代碼實現

伺服器實現:

package ex01.pyrmont;

import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.File;

public class HttpServer {

    /**
     * WEB_ROOT是HTML和其它文件存放的目錄. 這裡的WEB_ROOT為工作目錄下的webroot目錄
     */
    public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";

    // 關閉服務命令
    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";

    public static void main(String[] args) {
        HttpServer server = new HttpServer();
        //等待連接請求
        server.await();
    }

    public void await() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            //伺服器套接字對象
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }

        // 迴圈等待一個請求
        while (true) {
            Socket socket = null;
            InputStream input = null;
            OutputStream output = null;
            try {
                //等待連接,連接成功後,返回一個Socket對象
                socket = serverSocket.accept();
                input = socket.getInputStream();
                output = socket.getOutputStream();

                // 創建Request對象並解析
                Request request = new Request(input);
                request.parse();
                // 檢查是否是關閉服務命令
                if (request.getUri().equals(SHUTDOWN_COMMAND)) {
                    break;
                }

                // 創建 Response 對象
                Response response = new Response(output);
                response.setRequest(request);
                response.sendStaticResource();

                // 關閉 socket 對象
                socket.close();
                
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }
}

 Request類:

package ex01.pyrmont;

import java.io.InputStream;
import java.io.IOException;

public class Request {

    private InputStream input;
    private String uri;

    public Request(InputStream input) {
        this.input = input;
    }

    //從InputStream中讀取request信息,並從request中獲取uri值
    public void parse() {
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {
            request.append((char) buffer[j]);
        }
        System.out.print(request.toString());
        uri = parseUri(request.toString());
    }

    /**
     * 
     * requestString形式如下:
     * GET /index.html HTTP/1.1
     * Host: localhost:8080
     * Connection: keep-alive
     * Cache-Control: max-age=0
     * ...
     * 該函數目的就是為了獲取/index.html字元串
     */
    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 ex01.pyrmont;

import java.io.OutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.File;

/*
  HTTP Response = Status-Line
    *(( general-header | response-header | entity-header ) CRLF)
    CRLF
    [ message-body ]
    Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
*/

public class Response {

    private static final int BUFFER_SIZE = 1024;
    Request request;
    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];
        FileInputStream fis = null;
        try {
            //將web文件寫入到OutputStream位元組流中
            File file = new File(HttpServer.WEB_ROOT, request.getUri());
            if (file.exists()) {
                fis = new FileInputStream(file);
                int ch = fis.read(bytes, 0, BUFFER_SIZE);
                while (ch != -1) {
                    output.write(bytes, 0, ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
            } else {
                // file not found
                String errorMessage = "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>";
                output.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
            // thrown if cannot instantiate a File object
            System.out.println(e.toString());
        } finally {
            if (fis != null)
                fis.close();
        }
    }
}

結果測試

訪問存在的資源文件(註意存放在工程目錄的webroot文件夾里)

訪問不存在的資源文件:

關閉伺服器:

 

參考資料:《深入剖析Tomcat》

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 課本源碼部分 第9章 查找 - 二叉排序樹 ——《數據結構》-嚴蔚敏.吳偉民版 源碼使用說明 鏈接☛☛☛ 《數據結構-C語言版》(嚴蔚敏,吳偉民版)課本源碼+習題集解析使用說明 課本源碼合輯 鏈接☛☛☛ 《數據結構》課本源碼合輯 習題集全解析 鏈接☛☛☛ 《數據結構題集》習題解析合輯 本源碼引入的文 ...
  • 課本源碼部分 第9章 查找 - 次優查找樹 ——《數據結構》-嚴蔚敏.吳偉民版 源碼使用說明 鏈接☛☛☛ 《數據結構-C語言版》(嚴蔚敏,吳偉民版)課本源碼+習題集解析使用說明 課本源碼合輯 鏈接☛☛☛ 《數據結構》課本源碼合輯 習題集全解析 鏈接☛☛☛ 《數據結構題集》習題解析合輯 本源碼引入的文 ...
  • IPython從4.0開始,為了項目的獨立運行,便將notebook等一系列附加組件遷移至jupyter中,從而使得IPython專註於互動式python這一功能。讓我們來看看官網上的解釋: “IPython is a growing project, with increasingly langu ...
  • 轉~下麵列出Python正則表達式的幾種匹配用法: 此外,關於正則的一切http://deerchao.net/tutorials/regex/regex.htm 1.測試正則表達式是否匹配字元串的全部或部分 regex=ur"" #正則表達式 if re.search(regex, subject ...
  • 定義和用法 eval() 函數把字元串按照 PHP 代碼來計算。 該字元串必須是合法的 PHP 代碼,且必須以分號結尾。 如果沒有在代碼字元串中調用 return 語句,則返回 NULL。如果代碼中存在解析錯誤,則 eval() 函數返回 false。 語法 ? eval(phpcode) 參數描述 ...
  • 在c++中,當一個類含有虛函數的時候,類就具有了多態性。構造函數的一項重要功能就是初始化vptr指針,這是保證多態性的關鍵步驟。 構造函數初始化vptr指針 下麵是c++源碼: class X { private: int i; public: X(int ii) { i = ii; } virtu ...
  • 1.xml文件: 1 <?xml version="1.0" encoding="UTF-8"?><Students> 2 <student id="2"> 3 <name>ttt</name> 4 <age>44</age> 5 </student> 6 <student id="3"> 7 <n ...
  • 課本源碼部分 第9章 查找 - 斐波那契查找 ——《數據結構》-嚴蔚敏.吳偉民版 源碼使用說明 鏈接☛☛☛ 《數據結構-C語言版》(嚴蔚敏,吳偉民版)課本源碼+習題集解析使用說明 課本源碼合輯 鏈接☛☛☛ 《數據結構》課本源碼合輯 習題集全解析 鏈接☛☛☛ 《數據結構題集》習題解析合輯 本源碼引入的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...