使用socket模擬tomcat實現靜態資源處理
阿新 • • 發佈:2018-12-10
步驟:
1.服務端使用ServerSocket,監聽指定的埠。 2.呼叫ServerSocket的accept方法接收客戶端連線,得到Socket物件。 3.根據Socket物件的getInputStream()方法得到輸入流,從而拿到瀏覽器傳送的http請求的基本資訊。
GET /htmlfiles/test2.jsp HTTP/1.1 Host: localhost:9191 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 DNT: 1 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: Hm_lvt_9bd56a6d0766b887592ee921aa94763f=1500436957; __atuvc=47%7C35; _ga=GA1.1.2016651800.1504071340; Hm_lvt_4e003ba2028a4a83d95714c602ee7df5=1507970222; Hm_lvt_47acec2d282c3986f1b600abdc11c7ab=1520665960,1521097911,1521252255,1521540649
4.解析http請求,提取要訪問的資原始檔的位置,使用Socket的getOutputStream拿到輸出流,將檔案的內容寫到輸出流。 5.資源請求完畢,關閉相關的流和Socket。
程式碼
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(9191) ;
System.out.println("Server已在埠9191啟動!");
while (true) {
socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
Request request = new Request(inputStream);
OutputStream outputStream = socket. getOutputStream();
Response response = new Response(outputStream, request);
response.response();
outputStream.close();
inputStream.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class Request {
private String uri;
public Request(InputStream in) {
try {
String content = IOUtils.getRequestContent(in);
if (null == content || "".equals(content)) {
System.out.println("Bad request.");
return;
}
System.out.println("客戶端請求:\n" + content);
parseUri(content);
} catch (IOException e) {
e.printStackTrace();
}
}
private void parseUri(String content) {
this.uri = content.substring(content.indexOf("/"),content.indexOf("HTTP/")-1);
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
public class Response {
private Request request;
private OutputStream os;
public Response(OutputStream os, Request request) {
this.os = os;
this.request = request;
}
public void response() {
String uri = request.getUri();
if (null != uri && !"".equals(uri)) {
if (isResource()) {
String path = Http_Server.WEB_ROOT + uri.substring(1);
if (IOUtils.isFileExist(path)) {
IOUtils.writeFile(os, path);
} else {
String errorMessage = buildResponse("File Not Found","404","");
IOUtils.write(os, errorMessage.getBytes());
}
} else {
String errorMessage = buildResponse("動態請求暫不支援","200","OK");
IOUtils.write(os, errorMessage.getBytes());
}
}
}
private String buildResponse(String content, String statusCode, String statusMsg) {
String html = buildHTML(content);
int chineseCount = StringUtils.getChineseCharCount(html);
StringBuffer buffer = new StringBuffer();
buffer.append("HTTP/1.1 ")
.append(statusCode).append(" ")
.append(statusMsg).append("\r\n")
.append("Content-Type: text/html\r\n")
// .append("Content-Length: ")
// .append(html.length()+2*chineseCount) // 1箇中文字元佔3個位元組
.append("\r\n\r\n")
.append(html);
return buffer.toString();
}
private String buildHTML(String content) {
StringBuffer html = new StringBuffer();
html.append("<html>\n");
html.append("<head>\n");
html.append("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n");
html.append("</head>\n");
html.append("<body>\n");
html.append("<h1>").append(content).append("</h1>\n");
html.append("</body>\n");
html.append("</html>");
return html.toString();
}
private boolean isResource() {
String[] suffixs = {"html", "js", "css", "jpg", "jpeg", "gif", "bmp"};
for (String suf : suffixs) {
if (request.getUri().endsWith("." + suf)) {
return true;
}
}
return false;
}
}
public class IOUtils {
public static String getRequestContent(InputStream inputStream) throws IOException {
byte[] data = new byte[2048];
int len = inputStream.read(data);
if (len > 0) {
return new String(data,0,len);
}
return null;
}
public static boolean isFileExist(String path) {
File file = new File(path);
return file.exists();
}
public static byte[] getFileContent(String path) {
try {
File file = new File(path);
if (file.exists()) {
byte[] data = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(data);
return data;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void write(OutputStream os,byte[] data) {
try {
os.write(data);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeFile(OutputStream os,String path) {
FileInputStream fis = null;
try {
int BUFFER_SIZE = 1024;
fis = new FileInputStream(path);
byte[] data = new byte[BUFFER_SIZE];
int len = fis.read(data,0,BUFFER_SIZE);
boolean isFirst = true;
while (len != -1) {
if (isFirst) {
os.write("HTTP/1.0 200 OK\r\n".getBytes());
os.write("\r\n".getBytes());;// 根據 HTTP 協議, 空行將結束頭資訊
isFirst = false;
}
os.write(data,0,len);
len = fis.read(data,0,BUFFER_SIZE);
os.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Http_Server {
public final static String WEB_ROOT = Http_Server.class.getResource("/").getPath();
}
測試HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>測試頁面</title>
<link href="/htmlfiles/css/test.css" rel="stylesheet">
</head>
<body>
<h1>這是測試頁面。<br></h1>
<a href="http://localhost:9191/htmlfiles/images/1.jpg">點選開啟圖片</a>
</body>
</html>
資原始檔放在src目錄下。如圖:
測試
1.動態請求測試
2.不存在的靜態檔案
3.存在的靜態檔案
4.圖片等二進位制檔案測試
注意
1.你得通過響應頭告訴瀏覽器請求的狀態碼和資源型別,否則瀏覽器會告訴你這是無效的http響應。
os.write("HTTP/1.0 200 OK\r\n".getBytes());
os.write("\r\n".getBytes());;// 根據 HTTP 協議, 空行將結束頭資訊
2.如果指定了Content-Length,需要注意中文1個字元佔用3個位元組,否則會導致瀏覽器顯示不全。
buffer.append("Content-Length: ")
buffer.append(html.length()+2*chineseCount) // 1箇中文字元佔3個位元組