本文利用java自帶的socket編程實現(xiàn)了一個簡單的靜態(tài)資源服務器,可以響應靜態(tài)資源。本文一共有兩個版本的源碼。第一個版本名為Server_v1,該版本實現(xiàn)了一個簡單的socket的服務器,幫助讀者回憶socket編程。第二個版本名為Server_v2,該版本是對第一版的改良,給出了改良思路,做出了必要的封裝,讓其能夠響應css、html、jpg等靜態(tài)資源。
該版本實現(xiàn)一個簡單的socket服務器,針對瀏覽器的請求,能夠返回相應的頁面。
其源碼如下:
package mytomcat_v1;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;/** * * @author zhengrongjun * @version v1.0 */public class Server_V1 { public static void main(String[] args) { ServerSocket serverSocket = null; Socket client = null; try { serverSocket = new ServerSocket(9999); // 不斷接收客戶連接 while (true) { // 服務器阻塞等待客戶端socket連接過來 client = serverSocket.accept(); // 對客戶端里面端請求信息進行處理 InputStream in = client.getInputStream(); // 定義一個讀取緩沖池 主要是在inputstram流中讀取字節(jié) byte[] buff = new byte[1024]; int len = in.read(buff); if (len > 0) { String msg = new String(buff, 0, len); System.out.println("===="+msg+"======"); OutputStream out = client.getOutputStream(); //構建響應信息 StringBuffer sb = new StringBuffer(); sb.append("HTTP/1.1 200 OK\n"); sb.append("Content-Type: text/html; charset=UTF-8\n"); sb.append("\n"); String html="<html><head><title>賣燒餅咯</title></head></html><body>小曲經(jīng)常在" +"<font size='14' color='red'>" +new Date() +"</font>" +"<br/>賣燒餅</body></html>"; sb.append(html); out.write(sb.toString().getBytes()); out.flush(); out.close(); } } } catch (Exception e) { } }}
執(zhí)行效果如下圖所示,打開chrome瀏覽器,在導航欄輸入
http://localhost:9999/docs/index.html
顯示如下圖所示
控制臺輸出如下圖所示
====GET /docs/index.html HTTP/1.1Host: localhost:9999Connection: keep-aliveUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9======
該版本在版本一的基礎上進行優(yōu)化,使其能夠有效的響應靜態(tài)資源
先看第一部分代碼優(yōu)化,如下圖所示
另外,我們需要對靜態(tài)資源進行響應,因此我們需要獲取輸入內容的靜態(tài)資源地址,即以下部分的內容。
uri = msg.substring(msg.indexOf("/"),msg.indexOf("HTTP/1.1") - 1);
綜上所述,我們有HttpRequest類如下所示
package mytomcat_v2;import java.io.IOException;import java.io.InputStream;/** * 對客戶端進行處理對業(yè)務類 * * @author zhengrongjun * */public class HttpRequest { private String uri; public String getUri() { return uri; } public HttpRequest(InputStream in) throws IOException { // 對我們對請求字節(jié)流進行解析 resolverRequest(in); } private void resolverRequest(InputStream in) throws IOException { // TODO Auto-generated method stub byte[] buff = new byte[1024]; int len = in.read(buff); if (len > 0) { String msg = new String(buff, 0, len); System.out.println("====" + msg + "======"); // 解析出來 uri uri = msg.substring(msg.indexOf("/"), msg.indexOf("HTTP/1.1") - 1); } else { System.out.println("bad Request!"); } }}
接下來是第二部分的代碼優(yōu)化,如下圖所示
package mytomcat_v2;/** * 封裝http響應信息 * @author zhengrongjun * */import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;public class HttpResponse { private OutputStream os = null; public HttpResponse(OutputStream os) { this.os = os; } public void writerFile(String path) throws IOException { FileInputStream fileInputStream = new FileInputStream(path); byte[] buff = new byte[1024]; int len = 0; // 構建響應信息 StringBuffer sb = new StringBuffer(); sb.append("HTTP/1.1 200 OK\n"); sb.append("Content-Type: text/html; charset=UTF-8\n"); sb.append("\n"); os.write(sb.toString().getBytes()); while ((len = fileInputStream.read(buff)) != -1) { os.write(buff, 0, len); } fileInputStream.close(); os.flush(); os.close(); }}
接下來我們構建測試類,構建之前我們先去找一些靜態(tài)資源文件。作者直接去apache的官網(wǎng)下把tomcat給下了下來,然后去如下目錄拷貝靜態(tài)資源文件
apache-tomcat-8.5.28/webapps/docs
將整個docs 文件夾拷貝至你的項目的根目錄下
apache-tomcat-8.5.28/webapps/ROOT/favicon.ico
將favicon.ico圖片拷貝至你的根目錄下
靜態(tài)資源在你的項目中的結構如下圖所示
現(xiàn)在上我們的Server_V2的代碼
package mytomcat_v2;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;/** * * @author zhengrongjun * @version v2.0 */public class Server_V2 { public static void main(String[] args) { ServerSocket serverSocket = null; Socket client = null; try { serverSocket = new ServerSocket(9999); // 不斷接收客戶連接 while (true) { // 服務器阻塞等待客戶端socket連接過來 client = serverSocket.accept(); // =========請求類處理======= InputStream in = client.getInputStream(); HttpRequest request = new HttpRequest(in); String requestUri = request.getUri(); // =========響應類處理======= OutputStream os = client.getOutputStream(); HttpResponse response = new HttpResponse(os); //請求格式是/html/login.html這種,需要把開頭的/刪除 response.writerFile(requestUri.substring(1)); client.close(); } } catch (Exception e) { e.printStackTrace(); } }}
測試結果如下:
在瀏覽器輸入
http://localhost:9999/docs/ssl-howto.html
效果如下
sb.append("HTTP/1.1 200 OK\n");sb.append("Content-Type: text/html; charset=UTF-8\n");sb.append("\n");
部分修改為
if(path.endsWith("css")) { sb.append("HTTP/1.1 200 OK\n"); sb.append("Content-Type: text/css; charset=UTF-8\n"); sb.append("\n"); }else { sb.append("HTTP/1.1 200 OK\n"); sb.append("Content-Type: text/html; charset=UTF-8\n"); sb.append("\n"); }
繼續(xù)啟動測試,效果如下
本文給出了兩個版本的靜態(tài)資源的服務器源碼,希望讀者能夠有所收獲。