Java socket 實現tomcat伺服器
一個基於java的web伺服器使用這兩個重要的類:java.net.Socket和java.net.ServerSocket,並通過HTTP訊息進行通訊。在實現Web伺服器之前有必要簡要說明一下超文字傳輸協議(HTTP)。
超文字傳輸協議(HTTP)
http是一種無狀態的請求和相應協議,請大家暫時記住無狀態這一概念,在後續介紹session時將會向大家闡述有狀態和無狀態的區別。在HTTP中,始終由客戶端傳送HTTP請求。web伺服器從不主動聯絡客戶端或對客戶端做回撥連線,伺服器端只根據客戶端發來的請求做出響應。下面將介紹HTTP請求和HTTP響應和Socket類
HTTP請求
一個HTTP請求包括三個組成部分:
1.方法—統一資源標示符(URI)—協議/版本
2.請求的頭部
3.主體內容
示例如下:
- POST /examples/default.jsp HTTP/1.1
- Accept: text/plain; text/html
- Accept-Language: en-gb
- Connection: Keep-Alive
- Host: localhost
- User-Agent: Mozilla/4.0
- Content-Length: 33
-
Content-Type: application/x-www-form-urlencoded
- Accept-Encoding: gzip, deflate
- lastName=Franks&firstName=Michael
HTTP響應
類似於HTTP請求,一個HTTP響應也包括三個組成部分:
1.方法-統一資源標示符(URI)-協議/版本
2.響應的頭部
3.主體內容
下面是一個HTTP響應的例子:
- HTTP/1.1 200 OK
- Server: IBM/4.0
- Date: Sat, 6 Nov 2013 13:13:00 GMT
- Content-Type: text/html
-
Last-Modified: Sat, 5 Jan 2013 13:13:12 GMT
- Content-Length: 112
套接字是網路連線的一個端點。套接字使得一個應用可以從網路中讀取和寫入資料。放在兩個不同的計算機上的兩個應用可以通過連線傳送和接受位元組流。為了從你的應用傳送一條資訊到另一個應用,你需要指導另一個應用的IP地址和套接字埠。
ServerSocket類
Socket類代表一個客戶端套接字,即任何時候你想連線到一個遠端伺服器應用的時候你構造的套接字。如果是一個伺服器程式依靠Socket類是行不通的。你的伺服器必須隨時待命,因為客戶端何時想你傳送請求是不知道的。
ServerSocket和Socket不同,伺服器套接字的角色是等待來自客戶端的連線請求。一旦伺服器套接字獲得一個連線請求,它建立一個Socket例項來與客戶端進行通訊。
下面我們來看看這三個類:
HttpServer類
- <strong>package com.vipshop.test;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.net.UnknownHostException;
- import com.vipshop.tomcat.pyrmont.Request;
- import com.vipshop.tomcat.pyrmont.Response;
- publicclass HttpServer {
- publicstaticfinal String WEB_ROOT = System.getProperty("user.dir")
- + File.separator + "webroot";
- privatestaticfinal String SHUTDOWN_COMMAND = "/SHUTDOWN";
- privateboolean shutdown = false;
- publicstaticvoid main(String[] args) {
- HttpServer server = new HttpServer();
- server.await();
- }
- publicvoid await() {
- ServerSocket serverSocket = null;
- int port = 8080;
- try {
- serverSocket = new ServerSocket(port, 1, InetAddress
- .getByName("127.0.0.1"));
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- System.exit(1);
- }
- // Loop waiting for a request
- while (!shutdown) {
- Socket socket = null;
- InputStream input = null;
- OutputStream output = null;
- try {
- socket = serverSocket.accept();
- input = socket.getInputStream();
- output = socket.getOutputStream();
- // create Request object and parse
- Request request = new Request(input);
- request.parse();
- // create Response object
- Response response = new Response(output);
- response.setRequest(request);
- response.sendStaticResource();
- // Close the socket;
- socket.close();
- // check if the revious URI is a shutdown command
- shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
- } catch (IOException e) {
- e.printStackTrace();
- continue;
- }
- }
- }
- }
- </strong>
Request類
- package com.vipshop.test;
- import java.io.IOException;
- import java.io.InputStream;
- publicclass Request {
- private InputStream input;
- private String uri;
- public Request(InputStream input) {
- this.input = input;
- }
- publicvoid parse() {
- // Read a set of characters from the socket
- StringBuffer request = new StringBuffer(2018);
- int i;
- byte[] buffer = newbyte[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.println();
- System.out.println("request.toString():");
- System.out.print(request.toString());
- System.out.println();
- uri = parseUri(request.toString());
- }