自己動手寫http伺服器---java版

來源:互聯網
上載者:User

最簡單的http伺服器,可下載源碼:http://download.csdn.net/detail/ajaxhu/6356885


大概介紹一下原理吧,瀏覽器開啟網頁可以簡單分為3個階段:

1.通過socket向伺服器發送一個符合一定格式的請求字串(裡麵包含了使用者輸入的網址),比如:

Accepttext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Encodinggzip, deflateAccept-Languagezh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3Connectionkeep-aliveHostlocalhost:8001User-AgentMozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0

2.伺服器收到瀏覽器的請求字串,解析出使用者所請求的網址,網址其實對應伺服器中的檔案。   例如 http:\\www.demo.com其實對應伺服器裡的 http:\\www.demo.com\index.html,伺服器會將index.html這個檔案讀取到byte數組中,並加上頭資訊(也是字串),返回給發送請求的瀏覽器。
3.瀏覽器接收到伺服器返回的位元組流,根據返回的頭資訊,判斷返回的byte數組原始的資料類型(網頁、圖片、其他),例如返回的頭資訊如下: 
Content-Type text/html
說明返回的byte數組原來是html頁面,瀏覽器會解析html頁面,顯示資料。如果伺服器返回的頭資訊如下:
Content-Type image/jpeg
說明返回的byte數組原來是圖片,瀏覽器會將byte數組儲存為圖片,顯示圖片。
下面給出源碼:註:1.要運行程式,需要在同目錄下建立webapp檔案夾,將想啟動並執行網站放入(暫時只支援html,jpg,gif,png)2.程式運行參數:可以無參數運行,預設綁定80連接埠,有可能會衝突。可添加一個參數設定連接埠,例如:java -jar MyHtmlServer.jar 80018001為綁定的連接埠號碼。3.運行程式後,在瀏覽器中輸入 http://localhost:連接埠號碼/資源路徑即可。例如綁定的是8001連接埠,在webapp檔案夾下有index.html檔案,現在需要訪問這個檔案,在瀏覽器中輸入:http://localhost:8001/index.html 即可訪問。如果綁定的是80連接埠,可直接寫:http://localhost/index.html,瀏覽器預設使用80作為伺服器連接埠。源碼:
import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.InterruptedIOException;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class MyHtmlServer {public static void main(String[] args) throws IOException {int port=80;if(args.length>0)port=Integer.valueOf(args[0]);new MyHtmlServer().start(port);}/** * 在指定連接埠啟動http伺服器 * @param port 指定的連接埠 * @throws IOException */public void start(int port) throws IOException {ServerSocket server = new ServerSocket(port);System.out.println("server start at "+port+"...........");while (true) {Socket client = server.accept();ServerThread serverthread = new ServerThread(client);serverthread.start();}}/** * 伺服器響應線程,每收到一次瀏覽器的請求就會啟動一個ServerThread線程 * @author  * */class ServerThread extends Thread {Socket client;public ServerThread(Socket client) {this.client = client;}/** * 讀取檔案內容,轉化為byte數組 * @param filename 檔案名稱 * @return * @throws IOException */public  byte[] getFileByte(String filename) throws IOException{ByteArrayOutputStream baos=new ByteArrayOutputStream();File file=new File(filename);FileInputStream fis=new FileInputStream(file);byte[] b=new byte[1000];int read;while((read=fis.read(b))!=-1){baos.write(b,0,read);}fis.close();baos.close();return baos.toByteArray();}/** * 分析http請求中的url,分析使用者請求的資源,並將請求url正常化 * 例如請求 "/"要規範成"/index.html","/index"要規範成"/index.html" * @param queryurl 使用者原始的url * @return 正常化的url,即為使用者請求資源的路徑 */private String getQueryResource(String queryurl){String queryresource=null;int index=queryurl.indexOf('?');if(index!=-1){queryresource=queryurl.substring(0,queryurl.indexOf('?'));}elsequeryresource=queryurl;index=queryresource.lastIndexOf("/");if(index+1==queryresource.length()){queryresource=queryresource+"index.html";}else{String filename=queryresource.substring(index+1);if(!filename.contains("."))queryresource=queryresource+".html";}return queryresource;}/** * 根據使用者請求的資源類型,設定http回應標頭的資訊,主要是判斷使用者請求的檔案類型(html、jpg...) * @param queryresource * @return */private String getHead(String queryresource){String filename="";int index=queryresource.lastIndexOf("/");filename=queryresource.substring(index+1);String[] filetypes=filename.split("\\.");String filetype=filetypes[filetypes.length-1];if(filetype.equals("html")){return "HTTP/1.0200OK\n"+"Content-Type:text/html\n" + "Server:myserver\n" + "\n";}else if(filetype.equals("jpg")||filetype.equals("gif")||filetype.equals("png")){return "HTTP/1.0200OK\n"+"Content-Type:image/jpeg\n" + "Server:myserver\n" + "\n";}else return null;}@Overridepublic void run() {InputStream is;try {is = client.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));int readint;char c;byte[] buf = new byte[1000];OutputStream os = client.getOutputStream();client.setSoTimeout(50);byte[] data = null;String cmd = "";String queryurl = "";int state = 0;String queryresource;String head;while (true) {readint = is.read();c = (char) readint;boolean space=Character.isWhitespace(readint);switch (state) {case 0:if (space)continue;state = 1;case 1:if (space) {state=2;continue;}cmd+=c;continue;case 2:if(space)continue;state=3;case 3:if(space)break;queryurl+=c;continue;}break;}queryresource=getQueryResource(queryurl);head=getHead(queryresource);while (true) {try {if ((readint = is.read(buf)) > 0) {//System.out.write(buf);} else if (readint < 0)break;} catch (InterruptedIOException e) {data = getFileByte("webapp"+queryresource);}if (data != null) {os.write(head.getBytes("utf-8"));os.write(data);os.close();break;}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.