基于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

posted @ 2014-04-16 20:01  kyf  阅读(6072)  评论(0编辑  收藏  举报