基於HTTP的Web服務器編程


一、   內容概述

1.實驗目的

1)  掌握網絡應用程序的開發方法;2)  掌握Client/ Server結構軟件的設計與開發方法;3)  掌握Socket機制的工作原理。

2. 實驗前的准備

1)  閱讀教材關於TCP/IP協議和Socket的相關內容;2)  閱讀WinSock編程指南;3)  閱讀本實驗所附內容;4)  熟悉VC++、C#或Java開發語言。

3.實驗內容

1)利用Java語言,基於TCP編寫一個簡單的Web Server,要求可以實現單用戶簡單頁面瀏覽;2)修改上述Web Server,實現多用戶同時連接(多線程)請求。

4.實驗要求

1)  實現Web 服務器能發送文本文檔和圖片文件,Web 客戶端能接收服務器響應發來的文本文件和圖片文件,並能判斷通信時發生的一些簡單的錯誤。

2)  在實驗報告中要說明實現Web Server的主要步驟、關鍵類和作用、記錄實驗過程和實驗結果。

 

二、   設計要點及解決方案

    本實驗采用Java網絡編程技術開發;在服務器端和客戶端分別使用ServerSocket 和 Socket 來創建面向字節流、面向連接的TCP 套接字;在服務器端采用多線程來處理各個客戶的連接。模擬HTTP請求·應答模型進行 Web 服務器與Web客戶機間的通信。對文本文件與圖片文件數據的傳輸分別字符輸入輸出流和字節輸入輸出流,以便於處理。(文本文檔僅限於 *.html *.htm)

 

服務器程序的基本流程是:

1)  創建服務器端套接字並調用其accept( )等待接受客戶端的連接請求。

2)  當與新的客戶端連接之后,創建並啟動一個新的線程來處理這個新的連接。主線程繼續等待接受其他客戶端的連接。

3)  與客戶端進行通信為客戶端提供服務。首先,接受客戶端發來的HTTP請求消息;然后,判斷該請求是否正確,若錯誤,則繼續判斷是請求消息的書寫格式不正確還是服務器端找不到請求的文件錯誤,若正確,則繼續判斷請求的文件類型:文本文件或圖片文件;最后,根據判斷的結果向客戶端發送HTTP應答消息。

4)  關閉輸入輸出流、關閉套接字,繼續等待接受其他客戶端的連接。

 

客戶端程序的基本流程是:

1) 創建與服務器端連接的套接字。

2) 從標准輸入接受用戶輸入的URL,向Web 服務器發送請求該URL代表的資源的請求消息。

3) 接受服務器發來的應答消息並進行處理。首先,根據應答消息狀態行和首部判斷應答消息的類型,若狀態行的原因短語為“錯誤請求”或“文件找不到”,則置BadRequireFlag 為1,退出程序;否則,然后,根據"Content-Type:"判斷應答主體的類型:字符流或字節流,根據判斷結果啟用相應的輸入輸出流讀寫數據。

4) 退出程序。

 

三、   源代碼

  1 /**
  2  * @(#)HttpServer.java
  3  *
  4  * HttpServer application
  5  *
  6  * @author 鄺翼飛
  7  * @version 1.00 2010/12/15
  8  */
  9   
 10 import java.io.*;
 11 import java.net.*;
 12 import java.util.*;
 13 import java.text.*;
 14 
 15 public class HttpServer 
 16 {
 17     
 18     public static void main(String[] args) 
 19     {
 20         String root="D:\\httpserver";
 21         int port=800;
 22         int count=20;
 23         ServerSocket SvrSock;
 24         
 25         try
 26         {
 27             SvrSock=new ServerSocket(port,count);
 28             System.out.println("Server has started. Begin listening...");
 29             
 30             while(true)
 31             {
 32                 Socket Client=SvrSock.accept();
 33                 InetAddress clientAddress=Client.getInetAddress();
 34                 System.out.println("Client: "+clientAddress.toString()+ " has connected");
 35                 serviceThread st=new serviceThread(Client,root);
 36                 st.start();
 37             }
 38         }
 39         catch(IOException e)
 40         {
 41             System.out.println("Server Exception !");
 42             e.printStackTrace();
 43         }
 44     }
 45 }
 46 
 47 class serviceThread extends Thread
 48 {
 49     private String root;
 50     private File file;
 51     private final String NEWLINE="\r\n";
 52     private String requestfile;
 53     private String FileType;
 54     private Socket client;
 55     private InetAddress cAddress;
 56     private BufferedReader in;
 57     private PrintStream out;
 58     private DataOutputStream out2;
 59     private int errflag=-1;
 60     
 61     public serviceThread(Socket s,String root)
 62     {
 63         client=s;
 64         cAddress=s.getInetAddress();
 65         this.root=root;
 66         FileType=".html";
 67     }
 68     
 69     public void run()
 70     {
 71         try
 72         {
 73             in=new BufferedReader(new InputStreamReader(client.getInputStream()));
 74             out=new PrintStream(client.getOutputStream(),true);
 75             
 76             System.out.println("來自客戶端的請求消息:");
 77             System.out.println("-----------------------------------");
 78             String type=in.readLine();
 79             System.out.println(type);
 80             String sss=new String("");
 81             char ch[]={1,2,3,4,5};
 82             while(true)
 83             {                
 84                 sss=in.readLine();                
 85                 if(sss.equals(String.valueOf(ch)))
 86                     break;
 87                 System.out.println(sss);
 88             }
 89             System.out.println("-----------------------------------");
 90             
 91             int testtype=testType(type);
 92             if(testtype==-1)
 93             {
 94                 if(errflag==0)
 95                 {
 96                     System.out.println("客戶端請求格式錯誤");
 97                     sendHead(400,FileType,0);
 98                 }
 99                 else
100                 {
101                     System.out.println("文件未找到");
102                     sendHead(404,FileType,0);
103                 }
104             }
105             else
106             {
107                 try
108                 {            
109                     FileInputStream fins=new FileInputStream(requestfile);
110                     long filesize=fins.available();
111                     switch(testtype)
112                     {
113                         case 0:            
114                             BufferedReader fin=new BufferedReader(new FileReader(requestfile));
115                             if(fins!=null)
116                             {                        
117                                 sendHead(200,FileType,filesize);
118                         
119                                 String ss=fin.readLine();
120                                 while(ss!=null)
121                                 {
122                                     out.println(ss);
123                                     ss=fin.readLine();
124                                 }
125                                 //out.println(NEWLINE);                        
126                                 out.println(String.valueOf(ch));
127                                 out.flush();    
128                                 fins.close();
129                                 fin.close();
130                             }
131                             break;
132                         case 1:
133                             DataInputStream fin2=new DataInputStream(new BufferedInputStream(fins));
134                             out2=new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
135                     
136                             if(fins!=null)
137                             {
138                                 sendHead(200,FileType,filesize);
139                         
140                                 int count=0;
141                                 int i;
142                                 while((i=fin2.read())!=-1)
143                                 {
144                                     out2.write(i);
145                                     count++;
146                                 }
147                                 out2.flush();
148                                 fins.close();
149                                 out2.close();
150                                 System.out.println("Bytes number: "+count);
151                             }
152                             break;
153                         default: break;
154                     }
155                 }
156                 catch(FileNotFoundException e)
157                 {
158                     System.out.println("文件未找到");
159                     sendHead(404,FileType,0);
160                 }
161             }
162                                             
163             System.out.println("數據響應已完成\n");
164             client.close();
165         }
166         catch(IOException e)
167         {
168             System.out.println("run() service exception !");
169             e.printStackTrace();
170         }
171     }
172     
173     public int testType(String filetype)
174     {
175         int type=-1;
176         
177         filetype=filetype.substring(3,filetype.length()-8).trim(); // 獲取請求的Url
178         if((!filetype.startsWith("/")) && (!filetype.startsWith("\\")))
179         {
180             errflag=0;
181             return type;
182         }
183         requestfile=root+filetype;
184         requestfile=requestfile.replace('/','\\');
185         if(filetype.indexOf('.')!=-1)
186         {    
187             FileType=filetype.substring(filetype.lastIndexOf('.'));
188             boolean istxt=FileType.endsWith(".html") || FileType.endsWith(".htm");
189             boolean ispic=FileType.endsWith(".gif") || FileType.endsWith(".jpg") || FileType.endsWith(".bmp") || FileType.endsWith(".jpeg");
190             if(istxt)
191                 type=0;
192             else if(ispic)
193                 type=1;
194         }
195         else
196             errflag=0;
197         return type;
198     }
199     
200     public void sendHead(int code,String type,long size)
201     {
202         String message;
203         String state="OK";
204         message="HTTP/1.1 ";
205         
206         switch(code)
207         {
208             case 200:
209                 state=" 請求成功"; break;
210             case 400:
211                 state=" 錯誤請求"; break;
212             case 404:
213                 state=" 文件找不到"; break;
214             default:
215                 state=" OK"; break;
216         }
217         message += String.valueOf(code) + state + NEWLINE;
218         
219         SimpleDateFormat df=new SimpleDateFormat("E yyyy-MM-dd HH:mm:ss");
220         message +="Date: " +df.format(new Date()) + NEWLINE;
221         
222         if(FileType.equals(".jpg") || FileType.equals(".gif") || FileType.equals(".jpeg") || FileType.equals(".bmp"))
223             message += "Content-Type: image/"+FileType.substring(1)+NEWLINE;
224         else
225             message += "Content-Type: text/"+FileType.substring(1)+NEWLINE;
226         
227         message += "Content-Length: "+String.valueOf(size)+NEWLINE+NEWLINE;
228         out.print(message);
229         out.flush();
230     }
231 }
  1 /**
  2  * @(#)HttpClient.java
  3  *
  4  * HttpClient application
  5  *
  6  * @author 鄺翼飛
  7  * @version 1.00 2010/12/15
  8  */
  9  
 10 import java.io.*;
 11 import java.net.*;
 12 import java.util.*;
 13 
 14 
 15 public class HttpClient 
 16 {
 17     private String root;
 18     private BufferedReader in;
 19     private BufferedWriter out;
 20     private DataInputStream  in2;
 21     private DataOutputStream out2;
 22     private PrintStream txtFile;
 23     private Boolean head;
 24     
 25     public static void main(String[] args) 
 26     {
 27         HttpClient httpclient;
 28         if(args.length==1)
 29             httpclient=new HttpClient(args[0],800,"D:\\httpclient");
 30         else    
 31             httpclient=new HttpClient("localhost",800,"D:\\httpclient");
 32         System.out.print("請輸入URL:");
 33         String urlstr=new Scanner(System.in).nextLine();
 34         httpclient.send(urlstr);
 35         System.out.println("來自服務器的應答");
 36         System.out.println("-----------------------------------");
 37         httpclient.response();
 38     }
 39     
 40     public HttpClient(String address,int port,String root)
 41     {
 42         try
 43         {
 44             this.root=root;
 45             head=true;
 46             Socket socket=new Socket(address,port);
 47             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
 48             out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
 49             in2=new DataInputStream(new BufferedInputStream(socket.getInputStream()));
 50             System.out.println("與服務器的連接已建立.");
 51         }
 52         catch(IOException e)
 53         {
 54             System.out.println("Create socket to server failed !");
 55             e.printStackTrace();
 56             System.exit(1);
 57         }
 58     }
 59     
 60     public void send(String Url)
 61     {
 62         String ss=null;
 63         try
 64         {
 65             if(Url.equals("/") || Url.equals("/index.html") || Url.equals("www.kuangyifei.com") 
 66                                || Url.equals("http://www.kuangyifei.com"))
 67                  ss="GET /index.html HTTP/1.1\r\n";
 68             else if(Url.startsWith("www.kuangyifei.com/") || Url.startsWith("http://www.kuangyifei.com/"))
 69                 ss="GET " + Url.substring(Url.indexOf('/')) + " HTTP/1.1\r\n";
 70             else
 71                 ss="GET " + Url + " HTTP/1.1\r\n";
 72              
 73             ss+="Accept: text/html\r\n";
 74             ss+="Accept: image/gif, image/x-xbitmap, image/jpg, image/jpeg\r\n";
 75             ss+="Host: www.kuangyifei.com\r\n";
 76             ss+="Connection: Keep-Alive\r\n";
 77             out.write(ss);
 78             char ch[]={1,2,3,4,5};
 79             out.write(String.valueOf(ch)+"\r\n");
 80             out.flush();
 81         }
 82         catch(IOException e)
 83         {
 84             System.out.println("Send Exception !");
 85             e.printStackTrace();
 86         }
 87     }
 88     
 89     public void response() 
 90     {
 91         String line,ss;
 92         StringTokenizer st;
 93         String type="text";    
 94         int i;
 95         
 96         try
 97         {
 98             File TxtFile;
 99             File PicFile;
100             BufferedWriter outfile;
101             int contentlength=0;
102             int BadRequireFlag=0;
103             while((line=in.readLine())!=null)
104             {
105                 if(line.equals(""))
106                     if(head)
107                         head=false;
108                 if(head)
109                 {
110                     System.out.println(line);
111                     st=new StringTokenizer(line);
112                     ss=st.nextToken();
113                     if(ss.equals("HTTP/1.1"))
114                     {
115                         ss=st.nextToken();ss=st.nextToken();
116                         if(ss.equals("錯誤請求") || ss.equals("文件找不到"))
117                             BadRequireFlag=1;
118                     }
119                     if(ss.equals("Content-Type:"))
120                     {
121                         ss=st.nextToken();
122                         i=ss.indexOf('/');
123                         String substr=ss.substring(0,i);
124                         if(substr.equals("text"))
125                             type="text";                             
126                         else
127                         {
128                             type="pic";
129                             String substr2=ss.substring(i+1);
130                             PicFile=new File(root,"PicFile."+substr2) ;
131                             out2=new DataOutputStream(new FileOutputStream(PicFile));
132                         }                         
133                     }
134                     if(ss.equals("Content-Length:"))
135                     {
136                         ss=st.nextToken();
137                         contentlength=Integer.parseInt(ss);
138                     }
139                                             
140                 }
141                 else if(BadRequireFlag==1)
142                 {
143                     System.out.println("-----------------------------------");
144                     System.exit(1);
145                 }
146                 else 
147                 {
148                     if(type.equals("text"))
149                     {
150                         TxtFile=new File("D:\\httpclient","TxtFile.html") ;                          
151                         outfile=new BufferedWriter(new FileWriter(TxtFile));
152                         int count=0;
154                         char ch[]={1,2,3,4,5};
156                         while(line!=null)
157                         {
158                             System.out.println(line);
159                             outfile.append(line+"\r\n");
160                             outfile.flush();
161                             line=in.readLine();
162                             if(line.equals(String.valueOf(ch)))
163                                 break;
164                         }
165                         System.out.println("-----------------------------------");
166                         System.out.println("數據已成功傳輸完畢");
167                         outfile.close();in.close();
168                         break;                                
169                     }
170                     else if(type.equals("pic"))
171                     {
172                         int ch=in2.read();
173                         while(ch!=-1)                                       
174                         {
175                             out2.write(ch);
176                             ch=in2.read();
177                         }
178                         out2.flush();
179                         in2.close();
180                         out2.close();
181                         System.out.println("-----------------------------------");
182                         System.out.println("數據已成功傳輸完畢");
183                         break;
184                     }
185                     
186                 }
187             }
188         }
189         catch(IOException e)
190         {
191             System.out.println("Response exception !");
192             e.printStackTrace();
193         }
194     }
195 }

 

四、   運行截圖

    說明:運行的過程是:開啟服務器端, 開啟四個客戶端,四個客戶端分別向服務器端發送請求,請求的格式分別是:根文件夾中存在的文本文件、根文件夾中存在的圖片文件、不正確的格式、根文件夾中 不存在的文件。另外由於電腦不夠,只能在本機測試,所以所有的客戶端的IP地址均為:127.0.0.1。

  1. 服務器端運行截圖:

 

  1. 客戶端運行截圖:

客戶端1:IP地址 127.0.0.1

 

 

客戶端2:IP地址 127.0.0.1

 

客戶端3:IP地址 127.0.0.1

 

 

客戶端4:IP地址 127.0.0.1


免責聲明!

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



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