注:本段內容來源於《JAVA 實現 簡單的 HTTP服務器》html
狀態碼
|
狀態碼英文名稱
|
中文描述
|
---|---|---|
100
|
Continue
|
繼續。客戶端應繼續其請求
|
101
|
Switching Protocols
|
切換協議。服務器根據客戶端的請求切換協議。只能切換到更高級的協議,例如,切換到HTTP的新版本協議
|
200
|
OK
|
請求成功。通常用於GET與POST請求
|
201
|
Created
|
已建立。成功請求並建立了新的資源
|
202
|
Accepted
|
已接受。已經接受請求,但未處理完成
|
203
|
Non-Authoritative Information
|
非受權信息。請求成功。但返回的meta信息不在原始的服務器,而是一個副本
|
204
|
No Content
|
無內容。服務器成功處理,但未返回內容。在未更新網頁的狀況下,可確保瀏覽器繼續顯示當前文檔
|
205
|
Reset Content
|
重置內容。服務器處理成功,用戶終端(例如:瀏覽器)應重置文檔視圖。可經過此返回碼清除瀏覽器的表單域
|
206
|
Partial Content
|
部份內容。服務器成功處理了部分GET請求
|
300
|
Multiple Choices
|
多種選擇。請求的資源可包括多個位置,相應可返回一個資源特徵與地址的列表用於用戶終端(例如:瀏覽器)選擇
|
301
|
Moved Permanently
|
永久移動。請求的資源已被永久的移動到新URI,返回信息會包括新的URI,瀏覽器會自動定向到新URI。從此任何新的請求都應使用新的URI代替
|
302
|
Found
|
臨時移動。與301相似。但資源只是臨時被移動。客戶端應繼續使用原有URI
|
303
|
See Other
|
查看其它地址。與301相似。使用GET和POST請求查看
|
304
|
Not Modified
|
未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端一般會緩存訪問過的資源,經過提供一個頭信息指出客戶端但願只返回在指定日期以後修改的資源
|
305
|
Use Proxy
|
使用代理。所請求的資源必須經過代理訪問
|
306
|
Unused
|
已經被廢棄的HTTP狀態碼
|
307
|
Temporary Redirect
|
臨時重定向。與302相似。使用GET請求重定向
|
400
|
Bad Request
|
客戶端請求的語法錯誤,服務器沒法理解
|
401
|
Unauthorized
|
請求要求用戶的身份認證
|
402
|
Payment Required
|
保留,未來使用
|
403
|
Forbidden
|
服務器理解請求客戶端的請求,可是拒絕執行此請求
|
404
|
Not Found
|
服務器沒法根據客戶端的請求找到資源(網頁)。經過此代碼,網站設計人員可設置"您所請求的資源沒法找到"的個性頁面
|
405
|
Method Not Allowed
|
客戶端請求中的方法被禁止
|
406
|
Not Acceptable
|
服務器沒法根據客戶端請求的內容特性完成請求
|
407
|
Proxy Authentication Required
|
請求要求代理的身份認證,與401相似,但請求者應當使用代理進行受權
|
408
|
Request Time-out
|
服務器等待客戶端發送的請求時間過長,超時
|
409
|
Conflict
|
服務器完成客戶端的PUT請求時可能返回此代碼,服務器處理請求時發生了衝突
|
410
|
Gone
|
客戶端請求的資源已經不存在。410不一樣於404,若是資源之前有如今被永久刪除了可以使用410代碼,網站設計人員可經過301代碼指定資源的新位置
|
411
|
Length Required
|
服務器沒法處理客戶端發送的不帶Content-Length的請求信息
|
412
|
Precondition Failed
|
客戶端請求信息的先決條件錯誤
|
413
|
Request Entity Too Large
|
因爲請求的實體過大,服務器沒法處理,所以拒絕請求。爲防止客戶端的連續請求,服務器可能會關閉鏈接。若是隻是服務器暫時沒法處理,則會包含一個Retry-After的響應信息
|
414
|
Request-URI Too Large
|
請求的URI過長(URI一般爲網址),服務器沒法處理
|
415
|
Unsupported Media Type
|
服務器沒法處理請求附帶的媒體格式
|
416
|
Requested range not satisfiable
|
客戶端請求的範圍無效
|
417
|
Expectation Failed
|
服務器沒法知足Expect的請求頭信息
|
500
|
Internal Server Error
|
服務器內部錯誤,沒法完成請求
|
501
|
Not Implemented
|
服務器不支持請求的功能,沒法完成請求
|
502
|
Bad Gateway
|
充當網關或代理的服務器,從遠端服務器接收到了一個無效的請求
|
503
|
Service Unavailable
|
因爲超載或系統維護,服務器暫時的沒法處理客戶端的請求。延時的長度可包含在服務器的Retry-After頭信息中
|
504
|
Gateway Time-out
|
充當網關或代理的服務器,未及時從遠端服務器獲取請求
|
505
|
HTTP Version not supported
|
服務器不支持請求的HTTP協議的版本,沒法完成處理
|
客戶端向服務器發送一個請求,服務器以一個狀態行做爲響應,響應的內容包括:消息協議的版本、成功或者錯誤編碼、服務器信息、實體元信息以及必要的實體內容。根據響應類別的類別,服務器響應裏能夠含實體內容,但不是全部的響應都有實體內容。本節僅簡述響應頭[13] 。java
響應頭第一行也稱爲狀態行,格式以下:web
HTTP-Version 空格 Status-Code 空格 Reason-Phrase CRLF瀏覽器
HTTP- Version表示HTTP版本,例如爲HTTP/1.1。Status- Code是結果代碼,用三個數字表示。Reason-Phrase是個簡單的文本描述,解釋Status-Code的具體緣由。Status-Code用於機器自動識別,Reason-Phrase用於人工理解。Status-Code的第一個數字表明響應類別,可能取5個不一樣的值。後兩個數字沒有分類做用。Status-Code的第一個數字表明響應的類別,後續兩位描述在該類響應下發生的具體情況,具體請參見:HTTP狀態碼 。緩存
HTTP/1.1協議中共定義了八種方法(有時也叫「動做」)來代表Request-URI指定的資源的不一樣操做方式:服務器
OPTIONS - 返回服務器針對特定資源所支持的HTTP請求方法。也能夠利用向Web服務器發送'*'的請求來測試服務器的功能性。網絡
HEAD- 向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠在沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應消息頭中的元信息。app
GET - 向特定的資源發出請求。注意:GET方法不該當被用於產生「反作用」的操做中,例如在web app.中。其中一個緣由是GET可能會被網絡蜘蛛等隨意訪問。socket
POST - 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。函數
PUT - 向指定資源位置上傳其最新內容。
DELETE - 請求服務器刪除Request-URI所標識的資源。
TRACE- 回顯服務器收到的請求,主要用於測試或診斷。
CONNECT - HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。
PATCH - 用來將局部修改應用於某一資源,添加於規範RFC5789。
方法名稱是區分大小寫的。當某個請求所針對的資源不支持對應的請求方法的時候,服務器應當返回狀態碼405(Method Not Allowed);當服務器不認識或者不支持對應的請求方法的時候,應當返回狀態碼501(Not Implemented)。
HTTP服務器至少應該實現GET和HEAD方法,其餘方法都是可選的。固然,全部的方法支持的實現都應當符合下述的方法各自的語義定義。此外,除了上述方法,特定的HTTP服務器還可以擴展自定義的方法。
注:本段內容來源於《一個簡單的Java web服務器實現》
一個簡單的Java web服務器實現,比較簡單,基於java.net.Socket和java.net.ServerSocket實現;
服務器實現:
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中建立一個html頁面,命名爲index.html,源碼以下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>Hello World!</h1> </body> </html>
如今啓動該WEB服務器,並請求index.html靜態頁面。
所對應的控制檯的輸出:
如此,一個簡單的http服務器便完成了。