java實現web服務器


java實現web服務器

參考:http://jingyan.baidu.com/article/48206aeafba520216ad6b3e0.html

完整項目代碼:http://yunpan.cn/QiJTQAhyIbzKd (提取碼:4f0e)

首先上代碼:

 1 /**
 2  * @author hewenwu  3  * 功能:模擬web服務程序  4  * 原理:java多線程、socket編程,TCP協議  5  */
 6 
 7 import java.io.*;  8 import java.net.*;  9 
 10 public class web_server{  11 
 12     public static void main(String args[]) {  13 
 14         int client_id = 1;    //初始化客戶端id為1,client_id唯一標識一個socket和與其對應的一個java線程
 15      
 16         int PORT = 5000;      //該服務程序監聽的端口
 17     
 18         ServerSocket server=null;    //服務端的serversocket
 19     
 20         Socket client=null;          //客戶端socket
 21 
 22         try{  23             server=new ServerSocket(PORT);     //實例化serverclient對象,監聽5000端口。一個web服務器只需要一個serversocket
 24 
 25             System.out.println("Web Server is listening on port:"+server.getLocalPort());  26             
 27             /*這里用到了一個無窮循環,讓serversocket始終報紙監聽,隨時接受客戶端程序的請求*/
 28             while(true) {  29 
 30                 client=server.accept(); //接受客戶機的連接請求
 31 
 32                 new ConnectionThread(client,client_id).start(); //為該client創建服務線程
 33 
 34                 client_id++;//客戶端標識加1
 35  }  36             
 37         }catch(Exception e) {  38             
 39  System.out.println(e);  40  }  41  }  42 }  43 
 44 
 45 
 46 /* 繼承子Thread類,ConnnectionThread類完成與一個Web瀏覽器的通信 */
 47 
 48 class ConnectionThread extends Thread {  49 
 50     public Socket client = null; // 連接Web瀏覽器的socket字
 51 
 52     public int counter = 0; // 計數器
 53 
 54     public ConnectionThread(Socket cl , int c) {  55         
 56         client=cl;  57         counter=c;  58  }  59 
 60 @SuppressWarnings("deprecation")  61 
 62 public void run()  63 {  64     try{  65         
 66         String destIP=client.getInetAddress().toString(); // 客戶機IP地址
 67 
 68         int destport=client.getPort(); // 客戶機端口號
 69 
 70         System.out.println("Connection "+counter+":connected to "+destIP+" on port "+destport+".");  71 
 72         PrintStream outstream=new PrintStream(client.getOutputStream());//獲取與客戶機的打印輸出流
 73 
 74         DataInputStream instream=new DataInputStream(client.getInputStream());//獲取從客戶機的數據輸入流
 75 
 76         String inline=instream.readLine(); // 讀取Web瀏覽器提交的請求信息
 77 
 78         System.out.println("Received:"+inline);  79 
 80         if (get_request_type(inline)) { // 如果是GET請求
 81 
 82             String filename=get_file_name(inline);  83 
 84             File file=new File(filename);  85 
 86             if (file.exists()) { // 若文件存在,則將文件送給Web瀏覽器
 87 
 88                 System.out.println(filename+" requested.");  89 
 90                 //發送HTML的head信息
 91                 
 92                 outstream.println("HTTP/1.0 200 OK");  93 
 94                 outstream.println("MIME_version:1.0");  95 
 96                 outstream.println("Content_Type:text/html");  97 
 98                 int len=(int)file.length();  99 
100                 outstream.println("Content_Length:"+len); 101 
102                 outstream.println(""); 103 
104                 //發送HTML正文信息
105                 sendfile(outstream,file); // 發送文件 106 
107                 //清空輸出流
108  outstream.flush(); 109   
110             } else { // 文件不存在時
111 
112                 String filenam="error.html"; 113 
114                 //得到錯誤信息頁面
115                 File file1=new File(filenam); 116 
117                 System.out.println(filename+" requested."); 118 
119                 //輸出HTML的頭信息
120                 outstream.println("HTTP/1.0 200 OK"); 121 
122                 outstream.println("MIME_version:1.0"); 123 
124                 outstream.println("Content_Type:text/html"); 125 
126                 int len=(int)file.length(); 127 
128                 outstream.println("Content_Length:"+len); 129 
130                 outstream.println(""); 131 
132                 //輸出錯誤信息文件
133                 sendfile(outstream,file1); // 發送文件 134 
135                 //清空緩沖區
136  outstream.flush(); 137  } 138  } 139 
140         //設置延時,等待文件傳送完畢
141         long m1=1; 142         while (m1<11100000) 143  { 144             m1++; 145             
146  } 147         
148         //關閉客戶端socket
149  client.close(); 150    
151     }catch(IOException e) { 152 
153         System.out.println("Exception:"+e); 154  } 155 } 156 
157 
158 /* 獲取請求類型是否為“GET” */
159 
160 boolean get_request_type(String s) { 161 
162     if (s.length()>0) 163 
164  { 165         if(s.substring(0,3).equalsIgnoreCase("GET")) 166 
167             return true; 168  } 169     
170     return false; 171 } 172 
173 /* 獲取要訪問的文件名 */
174 
175 String get_file_name(String s) { 176 
177     /*get請求的第一行信息格式為:“GET /books/?name=Professional%20Ajax HTTP/1.1” 178  String.substring(int i)方法是從第i個字符開始取,取出后面所有的字符 179  String.substring(int begin,int end)方法是取出從begin到end的所有字符 180       */
181     
182     String file_name = s.substring(s.indexOf(' ')+1);//這一條是把get后面所有的字符串取出來
183 
184     file_name = file_name.substring(0,file_name.indexOf(' ')); 185 
186     try{ 187 
188         if(file_name.charAt(0)=='/') 189 
190             file_name=file_name.substring(1); 191 
192     }catch(StringIndexOutOfBoundsException e) { 193 
194         System.out.println("Exception:"+e); 195  } 196 
197     if (file_name.equals("")) { 198         
199         file_name="index.html"; 200  } 201 
202     return file_name; 203 } 204 
205 /*把指定文件發送給Web瀏覽器 */ 
206 
207 void sendfile(PrintStream outs,File file){ 208 
209     try{ 210 
211         DataInputStream in=new DataInputStream(new FileInputStream(file)); 212 
213         int len=(int)file.length(); 214 
215         byte buf[]=new byte[len]; 216 
217  in.readFully(buf); 218 
219         outs.write(buf,0,len); 220 
221  outs.flush(); 222 
223  in.close(); 224 
225     }catch(Exception e){ 226 
227         System.out.println("Error retrieving file."); 228 
229         System.exit(1); 230         
231  } 232 } 233 }


web_server原理解析:

    該程序用到的2個最基本的技術:1、java多線程技術,比較簡單;2、socket編程技術。

    1、java多線程技術:每次當瀏覽器請求該服務器發送數據的時候,服務器都為這個請求新建一個線程(new Thread()),所有的線程獨立工作,因此一個web server能同時接受多個client的請求。(詳細的多線程技術參見其他文章)

    2、socket技術:socket分為ServerSocket和一般的Socket。web服務器中,必須要有一個ServerSocket對象,在新建ServerSocket對象時,要為其指定一個監聽端口:

new ServerSocket(5000);

    然后用一個無窮循環來循環檢測該端口有沒有請求:

    while(true) {
 

                 client=server.accept(); //接受客戶機的連接請求
  
                 new ConnectionThread(client,client_id).start(); //為該client創建服務線程
 
                 client_id++;//客戶端標識加1
            }

    當該端口接收到請求的時候,ServerSocket對象便接受該請求,並為該請求創建一個socket對象,該socket對象便可以與客戶端的socket對象之間交換數據,數據交換是基於TCP協議的。

    流程圖:

至於其他的數據流操作,可以參考其他資料,數據java基本操作。

 

完整的項目運行方案:

1、在Eclipse里新建java項目,添加一個類web_server.class,將上面的代碼復制進去,保存。

2、用記事本寫兩個HTML文件index.html和error.html,保存。

3、要運行該web server有2種方法:用Eclipse或者用dos命令:

用Eclipse:用Eclipse需要將index.html和error.html文件放入到項目文件夾與src同級的文件夾下,並且刷新Eclipse里面的項目:

運行該項目,即可。

用dos命令:首先用javac命令編譯web_server.java文件,得到web_server.class和ConnectionThread.class文件,將web_server.class、ConnectionThread.class、index.html和error.html文件放入同一個文件夾,然后用java web_server運行改程序即可。

瀏覽器訪問:在地址欄輸入:

http://localhost:5000/index.html,回車,可以看到訪問成功:

輸入:http://localhost:5000/index1.html,回車,由於沒有index1.html文件,所以訪問失敗:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM