日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
用Java編寫你自己的簡單HTTP服務(wù)器

HTTP是個大協(xié)議,完整功能的HTTP服務(wù)器必須響應(yīng)資源請求,將URL轉(zhuǎn)換為本地系統(tǒng)的資源名。響應(yīng)各種形式的HTTP請求(GET、POST等)。處理不存在的文件請求,返回各種形式的狀態(tài)碼,解析MIME類型等。但許多特定功能的HTTP服務(wù)器并不需要所有這些功能。例如,很多網(wǎng)站只是想顯示“建設(shè)中“的消息。很顯然,Apache對于這樣的網(wǎng)站是大材小用了。這樣的網(wǎng)站完全可以使用只做一件事情的定制服務(wù)器。Java網(wǎng)絡(luò)類庫使得編寫這樣的單任務(wù)服務(wù)器輕而易舉。

泉港網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項目制作,到程序開發(fā),運營維護(hù)。創(chuàng)新互聯(lián)公司成立于2013年到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司

定制服務(wù)器不只是用于小網(wǎng)站。大流量的網(wǎng)站如Yahoo,也使用定制服務(wù)器,因為與一般用途的服務(wù)器相比,只做一件事情的服務(wù)器通常要快得多。針對某項任務(wù)來優(yōu)化特殊用途的服務(wù)器很容易;其結(jié)果往往比需要響應(yīng)很多種請求的一般用途服務(wù)器高效得多。例如,對于重復(fù)用于多頁面或大流量頁面中的圖標(biāo)和圖片,用一個單獨的服務(wù)器處理會更好(并且還可以避免在請求時攜帶不必要的Cookie,因而可以減少請求/響應(yīng)數(shù)據(jù),從而減少下載帶寬,提升速度);這個服務(wù)器在啟動時把所有圖片文件讀入內(nèi)存,從RAM中直接提供這些文件,而不是每次請求都從磁盤上讀取。此外,如果你不想在包含這些圖片的頁面請求之外單獨記錄這些圖片,這個單獨服務(wù)器則會避免在日志記錄上浪費時間。

本篇為大家簡要演示三種HTTP服務(wù)器:

(1) 簡單的單文件服務(wù)器

(2) 重定向服務(wù)器

(3) 完整功能的HTTP服務(wù)器

簡單的單文件服務(wù)器

該服務(wù)器的功能:無論接受到何種請求,都始終發(fā)送同一個文件。這個服務(wù)器命名為SingleFileHTTPServer,文件名、本地端口和內(nèi)容編碼方式從命令行讀取。如果缺省端口,則假定端口號為80。如果缺省編碼方式,則假定為ASCII。

 
 
 
 
  1. import java.io.*;  
  2. import java.net.ServerSocket;  
  3. import java.net.Socket;  
  4.  
  5.  
  6. public class SingleFileHTTPServer extends Thread {  
  7.       
  8.     private byte[] content;  
  9.     private byte[] header;  
  10.     private int port=80;  
  11.       
  12.     private SingleFileHTTPServer(String data, String encoding,  
  13.                 String MIMEType, int port) throws UnsupportedEncodingException {  
  14.         this(data.getBytes(encoding), encoding, MIMEType, port);  
  15.     }  
  16.       
  17.     public SingleFileHTTPServer(byte[] data, String encoding, String MIMEType, int port)throws UnsupportedEncodingException {  
  18.         this.content=data;  
  19.         this.port=port;  
  20.         String header="HTTP/1.0 200 OK\r\n"+  
  21.             "Server: OneFile 1.0\r\n"+  
  22.             "Content-length: "+this.content.length+"\r\n"+  
  23.             "Content-type: "+MIMEType+"\r\n\r\n";  
  24.         this.header=header.getBytes("ASCII");  
  25.     }  
  26.       
  27.     public void run() {  
  28.         try {  
  29.             ServerSocket server=new ServerSocket(this.port);  
  30.             System.out.println("Accepting connections on port "+server.getLocalPort());  
  31.             System.out.println("Data to be sent:");  
  32.             System.out.write(this.content);  
  33.               
  34.             while (true) {  
  35.                 Socket connection=null;  
  36.                 try {  
  37.                     connection=server.accept();  
  38.                     OutputStream out=new BufferedOutputStream(connection.getOutputStream());  
  39.                     InputStream in=new BufferedInputStream(connection.getInputStream());  
  40.                       
  41.                     StringBuffer request=new StringBuffer();  
  42.                     while (true) {  
  43.                         int c=in.read();  
  44.                         if (c=='\r'||c=='\n'||c==-1) {  
  45.                             break;  
  46.                         }  
  47.                         request.append((char)c);  
  48.                           
  49.                     }  
  50.                           
  51.                         //如果檢測到是HTTP/1.0及以后的協(xié)議,按照規(guī)范,需要發(fā)送一個MIME首部  
  52.                         if (request.toString().indexOf("HTTP/")!=-1) {  
  53.                             out.write(this.header);  
  54.                         }  
  55.                           
  56.                         out.write(this.content);  
  57.                         out.flush();  
  58.                       
  59.                 } catch (IOException e) {  
  60.                     // TODO: handle exception  
  61.                 }finally{  
  62.                     if (connection!=null) {  
  63.                         connection.close();  
  64.                     }  
  65.                 }  
  66.             }  
  67.               
  68.         } catch (IOException e) {  
  69.             System.err.println("Could not start server. Port Occupied");  
  70.         }  
  71.     }  
  72.       
  73.     public static void main(String[] args) {  
  74.         try {  
  75.             String contentType="text/plain";  
  76.             if (args[0].endsWith(".html")||args[0].endsWith(".htm")) {  
  77.                 contentType="text/html";  
  78.             }  
  79.               
  80.             InputStream in=new FileInputStream(args[0]);  
  81.             ByteArrayOutputStream out=new ByteArrayOutputStream();  
  82.             int b;  
  83.             while ((b=in.read())!=-1) {  
  84.                 out.write(b);  
  85.             }  
  86.             byte[] data=out.toByteArray();  
  87.               
  88.             //設(shè)置監(jiān)聽端口  
  89.             int port;  
  90.             try {  
  91.                 port=Integer.parseInt(args[1]);  
  92.                 if (port<1||port>65535) {  
  93.                     port=80;  
  94.                 }  
  95.             } catch (Exception e) {  
  96.                 port=80;  
  97.             }  
  98.               
  99.             String encoding="ASCII";  
  100.             if (args.length>2) {  
  101.                 encoding=args[2];  
  102.             }  
  103.               
  104.             Thread t=new SingleFileHTTPServer(data, encoding, contentType, port);  
  105.             t.start();  
  106.               
  107.         } catch (ArrayIndexOutOfBoundsException e) {  
  108.              System.out.println("Usage:java SingleFileHTTPServer filename port encoding");  
  109.         }catch (Exception e) {  
  110.             System.err.println(e);// TODO: handle exception  
  111.         }  
  112.     }  

SingleFileHTTPServer類本身是Thread的子類。它的run()方法處理入站連接。此服務(wù)器可能只是提供小文件,而且只支持低吞吐量的web網(wǎng)站。由于服務(wù)器對每個連接所需完成的所有工作就是檢查客戶端是否支持HTTP/1.0,并為連接生成一兩個較小的字節(jié)數(shù)組,因此這可能已經(jīng)足夠了。另一方面,如果你發(fā)現(xiàn)客戶端被拒絕,則可以使用多線程。許多事情取決于所提供文件的大小,每分鐘所期望連接的峰值數(shù)和主機(jī)上Java的線程模型。對弈這個程序復(fù)雜寫的服務(wù)器,使用多線程將會有明顯的收益。

Run()方法在指定端口創(chuàng)建一個ServerSocket。然后它進(jìn)入無限循環(huán),不斷地接受連接并處理連接。當(dāng)接受一個socket時,就會由一個InputStream從客戶端讀取請求。它查看***行是否包含字符串HTTP。如果包含此字符串,服務(wù)器就假定客戶端理解HTTP/1.0或以后的版本,因此為該文件發(fā)送一個MIME首部;然后發(fā)送數(shù)據(jù)。如果客戶端請求不包含字符串HTTP,服務(wù)器就忽略首部,直接發(fā)送數(shù)據(jù)。***服務(wù)器關(guān)閉連接,嘗試接受下一個連接。

而main()方法只是從命令行讀取參數(shù)。從***個命令行參數(shù)讀取要提供的文件名。如果沒有指定文件或者文件無法打開,就顯示一條錯誤信息,程序退出。如果文件能夠讀取,其內(nèi)容就讀入byte數(shù)組data.關(guān)于文件的內(nèi)容類型,將進(jìn)行合理的猜測,結(jié)果存儲在contentType變量中。接下來,從第二個命令行參數(shù)讀取端口號。如果沒有指定端口或第二個參數(shù)不是0到65535之間的整數(shù),就使用端口80。從第三個命令行參數(shù)讀取編碼方式(前提是提供了)。否則,編碼方式就假定為ASCII。然后使用這些值構(gòu)造一個SingleFileHTTPServer對象,開始運行。這是唯一可能的接口。

下面是測試的結(jié)果:

命令行編譯代碼并設(shè)置參數(shù):

telnet:

首先,啟用telnet服務(wù)(如果不會,自行g(shù)oogle之),接著測試該主機(jī)的端口:

結(jié)果(可以看到請求的輸出內(nèi)容):

HTTP協(xié)議測試:

文檔(這是之前一篇文章--小車動畫的文檔):

重定向服務(wù)器

實現(xiàn)的功能——將用戶從一個Web網(wǎng)站重定向到另一個站點。下例從命令行讀取URL和端口號,打開此端口號的服務(wù)器可能速度會很快,因此不需要多線程。盡管日次,使用多線程可能還是會帶來一些好處,尤其是對于網(wǎng)絡(luò)帶寬很低、吞吐量很小的網(wǎng)站。在此主要是為了演示,所以,已經(jīng)將該服務(wù)器做成多線程的了。這里為了簡單起見,為每個連接都啟用了一個線程,而不是采用線程池?;蛟S更便于理解,但這真的有些浪費系統(tǒng)資源并且顯得低效。

 
 
 
 
  1. import java.io.BufferedInputStream;  
  2. import java.io.BufferedWriter;  
  3. import java.io.IOException;  
  4. import java.io.InputStreamReader;  
  5. import java.io.OutputStreamWriter;  
  6. import java.io.Reader;  
  7. import java.io.Writer;  
  8. import java.net.BindException;  
  9. import java.net.ServerSocket;  
  10. import java.net.Socket;  
  11. import java.util.Date;  
  12.  
  13.  
  14. public class Redirector implements Runnable {  
  15.  
  16.     private int port;  
  17.     private String newSite;  
  18.       
  19.     public Redirector(String site, int port){  
  20.         this.port=port;  
  21.         this.newSite=site;  
  22.     }  
  23.       
  24.     @Override 
  25.     public void run() {  
  26.         try {  
  27.             ServerSocket server=new ServerSocket(port);  
  28.             System.out.println("Redirecting connection on port" 
  29.                     +server.getLocalPort()+" to "+newSite);  
  30.               
  31.             while (true) {  
  32.                 try {  
  33.                     Socket socket=server.accept();  
  34.                     Thread thread=new RedirectThread(socket);  
  35.                     thread.start();  
  36.                 } catch (IOException e) {  
  37.                     // TODO: handle exception  
  38.                 }  
  39.             }  
  40.         } catch (BindException e) {  
  41.             System.err.println("Could not start server. Port Occupied");  
  42.         }catch (IOException e) {  
  43.             System.err.println(e);  
  44.         }  
  45.           
  46.     }  
  47.       
  48.     class RedirectThread extends Thread {  
  49.  
  50.         private Socket connection;  
  51.           
  52.         RedirectThread(Socket s) {  
  53.             this.connection=s;  
  54.         }  
  55.           
  56.         public void run() {  
  57.             try {  
  58.                 Writer out=new BufferedWriter(  
  59.                         new OutputStreamWriter(connection.getOutputStream(),"ASCII"));  
  60.                 Reader in=new InputStreamReader(  
  61.                         new BufferedInputStream(connection.getInputStream()));  
  62.                   
  63.                 StringBuffer request=new StringBuffer(80);  
  64.                 while (true) {  
  65.                     int c=in.read();  
  66.                     if (c=='\t'||c=='\n'||c==-1) {  
  67.                         break;  
  68.                     }  
  69.                     request.append((char)c);  
  70.                 }  
  71.                   
  72.                 String get=request.toString();  
  73.                 int firstSpace=get.indexOf(' ');  
  74.                 int secondSpace=get.indexOf(' ', firstSpace+1);  
  75.                 String theFile=get.substring(firstSpace+1, secondSpace);  
  76.                   
  77.                 if (get.indexOf("HTTP")!=-1) {  
  78.                     out.write("HTTP/1.0 302 FOUND\r\n");  
  79.                     Date now=new Date();  
  80.                     out.write("Date: "+now+"\r\n");  
  81.                     out.write("Server: Redirector 1.0\r\n");  
  82.                     out.write("Location: "+newSite+theFile+"\r\n");  
  83.                     out.write("Content-Type: text/html\r\n\r\n");  
  84.                     out.flush();  
  85.                 }  
  86.                   
  87.                 //并非所有的瀏覽器都支持重定向,  
  88.                 //所以我們需要生成一個適用于所有瀏覽器的HTML文件,來描述這一行為  
  89.                 out.write("Document moved\r\n");  
  90.                 out.write("

    Document moved

    \r\n");  
  91.                 out.write("The document "+theFile  
  92.                         +" has moved to \r\n
  93.                         +newSite+theFile  
  94.                         +".\r\n Please update your bookmarks");  
  95.                 out.write("\r\n");  
  96.                 out.flush();  
  97.                 } catch (IOException e) {  
  98.             }finally{  
  99.                 try {  
  100.                     if (connection!=null) {  
  101.                         connection.close();  
  102.                     }  
  103.                 } catch (IOException e2) {  
  104.                       
  105.                 }  
  106.             }  
  107.         }  
  108.           
  109.     }  
  110.       
  111.     /**  
  112.      * @param args  
  113.      */ 
  114.     public static void main(String[] args) {  
  115.         int thePort;  
  116.         String theSite;  
  117.           
  118.         try {  
  119.             theSite=args[0];  
  120.               
  121.             //如果結(jié)尾有'/',則去除  
  122.             if (theSite.endsWith("/")) {  
  123.                 theSite=theSite.substring(0,theSite.length()-1);  
  124.             }  
  125.         } catch (Exception e) {  
  126.             System.out.println("Usage: java Redirector http://www.newsite.com/ port");  
  127.             return;  
  128.         }  
  129.           
  130.         try {  
  131.             thePort=Integer.parseInt(args[1]);  
  132.         } catch (Exception e) {  
  133.             thePort=80;  
  134.         }  
  135.           
  136.         Thread t=new Thread(new Redirector(theSite, thePort));  
  137.         t.start();  
  138.  
  139.     }  
  140.       

HTTP測試:

偵聽8010端口,此處重定向到百度:

main()方法提供一個非常簡單的界面,讀取新網(wǎng)站的URL(為了把鏈接重定向到該URL)和監(jiān)聽本地端口。它使用這些信息構(gòu)造了一個Rredirector對象。然后它使用所生成的Runnable對象(Redirector實現(xiàn)了Runnable)來生成一個新線程并啟動。如果沒有指定端口,Rredirector則會監(jiān)聽80端口。

Redirectro的run()方法將服務(wù)器socket綁定與此端口,顯示一個簡短的狀態(tài)消息,然后進(jìn)入無限循環(huán),監(jiān)聽連接。每次接受連接,返回的Socket對象會用來構(gòu)造一個RedirectThread。然后這個RedirectThread被啟動。所有與客戶端進(jìn)一步的交互由此新線程完成。Redirector的run()方法只是等待下一個入站連接。

RedirectThread的run()方法完成了很多工作。它先把一個Writer鏈接到Socket的輸出流,把一個Reader鏈接到Socket的輸入流。輸入流和輸出流都有緩沖。然后run()方法讀取客戶端發(fā)送的***行。雖然客戶端可能會發(fā)送整個Mime首部,但我們會忽略這些。***行包含所有所需的信息。這一行內(nèi)容可能會是這樣:

GET /directory/filename.html HTTP/1.0

可能***個詞是POST或PUT,也可能沒有HTTP版本。

返回的輸出,***行顯示為:

HTTP/1.0 302 FOUND

這是一個HTTP/1.0響應(yīng)嗎,告知客戶端要被重定向。第二行是“Date:”首部,給出服務(wù)器的當(dāng)前時間。這一行是可選的。第三行是服務(wù)器的名和版本;這一行也是可選的,但蜘蛛程序可用它來統(tǒng)計記錄***的web服務(wù)器。下一行是“Location:”首部,對于此服務(wù)器這是必須的。它告知客戶端要重定向的位置。***是標(biāo)準(zhǔn)的“Content-type:”首部。這里發(fā)送內(nèi)容類型text/html,只是客戶端將會看到的HTML。***,發(fā)送一個空行來標(biāo)識首部數(shù)據(jù)的結(jié)束。

如果瀏覽器不支持重定向,那么那段HTML標(biāo)簽就會被發(fā)送。

功能完整的HTTP服務(wù)器

這里,我們來開發(fā)一個具有完整功能的HTTP服務(wù)器,成為JHTTP,它可以提供一個完整的文檔樹,包括圖片、applet、HTML文件、文本文件等等。它與SingleFileHTTPServer非常相似,只不過它所關(guān)注的是GET請求。此服務(wù)器仍然是相當(dāng)輕量級的;看過這個代碼后,我們將討論可能希望添加的其他特性。

由于這個服務(wù)器必須為可能很慢的網(wǎng)絡(luò)連接提供文件系統(tǒng)的大文件,因此要改變其方式。這里不再在執(zhí)行主線程中處理到達(dá)的每個請求,而是將入站連接放入池中。由一個RequestProcessor類實例從池中移走連接并進(jìn)行處理。

 
 
 
 
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.net.ServerSocket;  
  4. import java.net.Socket;  
  5.  
  6. import org.omg.CORBA.Request;  
  7.  
  8.  
  9. public class JHTTP extends Thread {  
  10.  
  11.     private File documentRootDirectory;  
  12.     private String indexFileName="index.html";  
  13.     private ServerSocket server;  
  14.     private int numThreads=50;  
  15.       
  16.     public JHTTP(File documentRootDirectory,int port , String indexFileName)throws IOException {  
  17.         if (!documentRootDirectory.isDirectory()) {  
  18.             throw new IOException(documentRootDirectory+" does not exist as a directory ");  
  19.         }  
  20.         this.documentRootDirectory=documentRootDirectory;  
  21.         this.indexFileName=indexFileName;  
  22.         this.server=new ServerSocket(port);  
  23.     }  
  24.       
  25.     private JHTTP(File documentRootDirectory, int port)throws IOException {  
  26.         this(documentRootDirectory, port, "index.html");  
  27.     }  
  28.       
  29.     public void run(){  
  30.         for (int i = 0; i < numThreads; i++) {  
  31.             Thread t=new Thread(new RequestProcessor(documentRootDirectory, indexFileName));  
  32.             t.start();  
  33.         }  
  34.           
  35.         System.out.println("Accepting connection on port " 
  36.                 +server.getLocalPort());  
  37.         System.out.println("Document Root: "+documentRootDirectory);  
  38.         while (true) {  
  39.             try {  
  40.                 Socket request=server.accept();  
  41.                 RequestProcessor.processRequest(request);  
  42.             } catch (IOException e) {  
  43.                 // TODO: handle exception  
  44.             }  
  45.         }  
  46.     }  
  47.       
  48.       
  49.     /**  
  50.      * @param args  
  51.      */ 
  52.     public static void main(String[] args) {  
  53.         File docroot;  
  54.         try {  
  55.             docroot=new File(args[0]);  
  56.         } catch (ArrayIndexOutOfBoundsException e) {  
  57.             System.out.println("Usage: java JHTTP docroot port indexfile");  
  58.             return;  
  59.         }  
  60.           
  61.         int port;  
  62.         try {  
  63.             port=Integer.parseInt(args[1]);  
  64.             if (port<0||port>65535) {  
  65.                 port=80;  
  66.             }  
  67.         } catch (Exception e) {  
  68.             port=80;  
  69.         }  
  70.           
  71.         try {  
  72.             JHTTP webserver=new JHTTP(docroot, port);  
  73.             webserver.start();  
  74.         } catch (IOException e) {  
  75.             System.out.println("Server could not start because of an "+e.getClass());  
  76.             System.out.println(e);  
  77.         }  
  78.           
  79.     }  
  80.  
  81. }  

JHTTP類的main()方法根據(jù)args[0]設(shè)置文檔的根目錄。端口從args[1]讀取,或者使用默認(rèn)的80.然后構(gòu)造一個新的JHTTP線程并啟動。此JHTTP線程生成50個RequestProcessor線程處理請求,每個線程在可用時從RequestProcessor池獲取入站連接請求。JHTTP線程反復(fù)地接受入站連接,并將其放在RequestProcessor池中。每個連接由下例所示的RequestProcessor類的run()方法處理。此方法將一直等待,直到從池中得到一個Socket。一旦得到Socket,就獲取輸入和輸出流,并鏈接到閱讀器和書寫器。接著的處理,除了多出文檔目錄、路徑的處理,其他的同單文件服務(wù)器。

 
 
 
 
  1. import java.io.BufferedInputStream;  
  2. import java.io.BufferedOutputStream;  
  3. import java.io.DataInputStream;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStreamReader;  
  8. import java.io.OutputStream;  
  9. import java.io.OutputStreamWriter;  
  10. import java.io.Reader;  
  11. import java.io.Writer;  
  12. import java.net.Socket;  
  13. import java.util.Date;  
  14. import java.util.List;  
  15. import java.util.LinkedList;  
  16. import java.util.StringTokenizer;  
  17.  
  18.  
  19. public class RequestProcessor implements Runnable {  
  20.  
  21.     private static List pool=new LinkedList();  
  22.     private File documentRootDirectory;  
  23.     private String indexFileName="index.html";  
  24.       
  25.     public RequestProcessor(File documentRootDirectory,String indexFileName) {  
  26.         if (documentRootDirectory.isFile()) {  
  27.             throw new IllegalArgumentException();  
  28.         }  
  29.         this.documentRootDirectory=documentRootDirectory;  
  30.         try {  
  31.             this.documentRootDirectory=documentRootDirectory.getCanonicalFile();  
  32.         } catch (IOException e) {  
  33.         }  
  34.           
  35.         if (indexFileName!=null) {  
  36.             this.indexFileName=indexFileName;  
  37.         }  
  38.     }  
  39.       
  40.     public static void processRequest(Socket request) {  
  41.         synchronized (pool) {  
  42.             pool.add(pool.size(),request);  
  43.             pool.notifyAll();  
  44.         }  
  45.     }  
  46.       

  47. 網(wǎng)頁名稱:用Java編寫你自己的簡單HTTP服務(wù)器
    網(wǎng)站URL:http://www.5511xx.com/article/dpsegic.html