Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1146317
  • 博文数量: 103
  • 博客积分: 1897
  • 博客等级: 上尉
  • 技术积分: 1717
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-19 21:02
文章分类

全部博文(103)

文章存档

2013年(19)

2012年(84)

分类: 系统运维

2012-09-06 14:17:08

最近自己在学习《how tomcat works》,特意mark一下一些学习心得。
我们知道web服务器是网络应用中不可缺失的一个环节,那么,一个简单的web服务器是怎么实现的呢?
一 HTTP
 http请求
 一般一个http请求包括以下三个部分:
 1 请求方法,如get,post
 2 请求头

 
3 实体
 
一个http请求的实例如下:
GET /index.jsp HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:15.0) Gecko/20100101 Firefox/15.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
注意红色部分的url,这是我们待会要截取出来的。
 http响应
与http请求类似,http响应也包括三个部分
1 协议-状态码-描述
2 响应头
3 响应实体段

二 socket类
套接字是网络连接的断点。套接字使得应用程序可以从网络中读取数据,可以向网络中写入数据。不同计算机上的应用程序可以通过套接字发送或接受字节流。java中提供了Socket类来实现这个功能,通过getInputStream和getOutputStream可以获取网络中的输入输出流。
  但是,光靠Socket类还是不能够实现我们构建一个服务器应用程序的功能的,因为服务器必须时刻待命,因此java里面提供了ServerSocket类来处理等待来自客户端的请求,当ServerSocket接受到了来自客户端的请求之后,它就会创建一个实例来处理与客户端的通信。
 
三 服务器应用程序的实现
首先,我们要构建一个封装请求信息的类requst,一个响应请求的类response,还要有一个主程序httpServer来处理客户端来的请求。



点击(此处)折叠或打开

  1. package com.lwq;

  2. import java.io.IOException;
  3. import java.io.InputStream;

  4. /**
  5.  * @author thomaslwq
  6.  * @version 创建时间:Sep 5, 2012 9:59:32 PM
  7.  * 类说明
  8.  * 将浏览器发来的请求信息转化成字符和截取url
  9.  */
  10. public class Request {
  11.     
  12.     //输入流
  13.     private InputStream input;
  14.     //截取url,如 ,截取部分为 /index.html
  15.     private String uri;
  16.     public Request(InputStream inputStream){
  17.         this.input = inputStream;
  18.     }
  19.     
  20.     public InputStream getInput() {
  21.         return input;
  22.     }
  23.     public void setInput(InputStream input) {
  24.         this.input = input;
  25.     }
  26.     public String getUri() {
  27.         return uri;
  28.     }
  29.     public void setUri(String uri) {
  30.         this.uri = uri;
  31.     }
  32.     
  33.     //从套接字中读取字符信息
  34.     public void parse(){
  35.         
  36.             StringBuffer request = new StringBuffer(2048);
  37.             int i = 0;
  38.             byte[] buffer = new byte[2048];
  39.             
  40.             try {
  41.                 i = input.read(buffer);
  42.             } catch (IOException e) {
  43.                 // TODO Auto-generated catch block
  44.                 e.printStackTrace();
  45.                 i = -1;
  46.             }
  47.             for(int j = 0;j<i;j++){
  48.                     request.append((char)(buffer[j]));
  49.             }
  50.             System.out.println(request.toString());
  51.             uri = parseUri(request.toString());
  52.             }
  53.     //截取请求的url
  54.     private String parseUri(String requestString){
  55.         
  56.         int index1 = 0;
  57.         int index2 = 0;
  58.         index1 = requestString.indexOf(' ');
  59.         if(index1!=-1){
  60.             index2 = requestString.indexOf(' ',index1+1);
  61.             if(index2>index1){
  62.                 return requestString.substring(index1+1,index2);
  63.             }
  64.         }
  65.         
  66.         return null;
  67.     }
  68.             
  69.             
  70.             
  71.         
  72.     }

下面是封装了响应请求的类response


点击(此处)折叠或打开

  1. package com.lwq;

  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.io.OutputStream;
  7. import java.io.PrintWriter;

  8. /**
  9.  * @author thomaslwq
  10.  * @version 创建时间:Sep 5, 2012 9:59:53 PM
  11.  * 类说明 根据相应信息返回结果
  12.  */
  13. public class Response {
  14.     
  15.     private static final int BUFFER_SIZE = 1024;
  16.     Request request;
  17.     OutputStream output;
  18.     public Response(OutputStream output){
  19.         this.output = output;
  20.     }
  21.     
  22.     public void sendStaticResource() throws IOException{
  23.         
  24.         byte[] bytes = new byte[BUFFER_SIZE];
  25.         FileInputStream fis = null;
  26.         
  27.         File file = new File(HttpServer.WEB_ROOT,request.getUri());
  28.         if(file.exists()){
  29.             try {
  30.                 fis = new FileInputStream(file);
  31.                 int ch = fis.read(bytes,0,BUFFER_SIZE);
  32.                 while(ch != -1){
  33.                     output.write(bytes,0,ch);
  34.                     ch = fis.read(bytes,0,BUFFER_SIZE);
  35.                 }
  36.                 
  37.             } catch (FileNotFoundException e) {
  38.                 // TODO Auto-generated catch block
  39.                 e.printStackTrace();
  40.             }catch(IOException e){
  41.                 e.printStackTrace();
  42.             }finally{
  43.                 if(fis !=null){
  44.                     fis.close();
  45.                 }
  46.             }
  47.             
  48.         }else{
  49.             //找不到文件
  50.              String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
  51.      "Content-Type: text/html\r\n" +
  52.      "Content-Length: 23\r\n" +
  53.      "\r\n" +
  54.      "

    File Not Found

    "
    ;
  55.              try {
  56.                 output.write(errorMessage.getBytes());
  57.                 output.flush();
  58.             } catch (IOException e) {
  59.                 // TODO Auto-generated catch block
  60.                 e.printStackTrace();
  61.             }
  62.         }
  63.     }
  64.     public Request getRequest() {
  65.         return request;
  66.     }
  67.     public void setRequest(Request request) {
  68.         this.request = request;
  69.     }
  70.     public OutputStream getOutput() {
  71.         return output;
  72.     }
  73.     public void setOutput(OutputStream output) {
  74.         this.output = output;
  75.     }
  76.     public static int getBUFFER_SIZE() {
  77.         return BUFFER_SIZE;
  78.     }
  79.     
  80.     

  81. }

接下来是主程序,

点击(此处)折叠或打开

  1. package com.lwq;

  2. import java.io.File;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.net.InetAddress;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;

  8. /**
  9.  * @author thomaslwq
  10.  * @version 创建时间:Sep 5, 2012 9:59:16 PM
  11.  * 类说明
  12.  */
  13. public class HttpServer {

  14.     /**
  15.      * @param args
  16.      */
  17.     
  18.     //WEB_ROOT是服务器的根目录
  19.     public static final String WEB_ROOT = System.getProperty("user.dir")+File.separator+"webroot";
  20.     
  21.     //关闭的命令
  22.     private static final String SHUTDOWN_COMMAND= "/SHUTDOWN";
  23.     
  24.     public static void main(String[] args) {
  25.         // TODO Auto-generated method stub
  26.         HttpServer server = new HttpServer();
  27.         server.await();

  28.     }
  29.     public void await(){
  30.         ServerSocket serverSocket = null;
  31.         int port = 8080;
  32.         try {
  33.             serverSocket = new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));
  34.             while(true)
  35.             {
  36.                 try {
  37.             Socket socket = null;
  38.             InputStream input = null;
  39.             OutputStream output = null;
  40.             socket = serverSocket.accept();
  41.             input = socket.getInputStream();
  42.             output = socket.getOutputStream();
  43.             //封装request请求
  44.             Request request = new Request(input);
  45.             request.parse();
  46.             //封装response对象
  47.             Response response = new Response(output);
  48.             response.setRequest(request);
  49.             response.sendStaticResource();
  50.             socket.close();
  51.                 } catch (Exception e) {
  52.                     // TODO Auto-generated catch block
  53.                     e.printStackTrace();
  54.                     continue;
  55.                 }
  56.             
  57.             }
  58.         } catch (Exception e) {
  59.             // TODO Auto-generated catch block
  60.             e.printStackTrace();
  61.         }
  62.         
  63.         
  64.         
  65.     }
  66.     

  67. }

运行httpServer,在浏览器中打下就能看到服务器响应的结果了。

附带工程源码



 SimpleWebServer.rar  
阅读(21299) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~