什么是HTTP服务器?要理解这个概念,我们先要知道HTTP协议。HTTP协议(HypertextTransferProtocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。这就是你为什么在浏览器中看到的网页地址都是以“http://”开头的原因。

 

由于HTTP协议是基于请求/响应范式的(相当于客户端/服务器)。一个客户端与服务器建立连接后,发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。

 

在WWW中,“客户端”与“服务器”是一个相对的概念,只存在于一个特定的连接期间,即在某个连接中的客户在另一个连接中可能作为服务器。基于HTTP协议的客户/服务器模式的信息交换过程,它分四个过程:建立连接、发送请求信息、发送响应信息、关闭连接。

 

现在我们就来做一个简易的http服务器程序,更深刻地理解它们的工作方式。这里我们做两个类HttpServer.java和HttpSession.java,同时我们将所有的web资源放在E://www目录下:

 

HttpServer.java:
package com.wepull.http;
 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
 
public class HttpServer {
 
   public void startServer() {
      ServerSocket ss = null;
      try {
        ss = new ServerSocket(80);
        while (true) {
           Socket s = ss.accept();
           new HttpSession(s).start();
        }
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } finally {
        try {
           ss.close();
        } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
      }
   }
 
   public static void main(String[] args) {
      HttpServer server = new HttpServer();
      server.startServer();
   }
}
 
 
HttpSession.java
package com.wepull.http;
 
import java.io.*;
import java.net.Socket;
import java.text.DateFormat;
import java.util.Date;
 
public class HttpSession extends Thread {
   public static final String PATH_NAME = "E://www//";
   private Socket s;
 
   public HttpSession(Socket s) {
      super();
      this.s = s;
   }
 
   @Override
   public void run() {
      BufferedReader br = null;
      OutputStream out = null;
      try {
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        out = s.getOutputStream();
        String line = "";
        while ((line = br.readLine()) != null) {
           if (line.equals("")) {
              break;
           }
           System.out.println(line);
           String[] cmds = line.split(" ");
           // 处理客户端更重要的指令
           if (cmds[0].equals("GET")) {
              String fileName = cmds[1].substring(1);
              if (fileName.equals("")) {
                 fileName = "index.htm";
              }
              doGet(out, PATH_NAME + fileName);
           }
 
        }
 
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } finally {
        try {
           br.close();
           out.close();
           s.close();
        } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
      }
   }
 
   private void printOkResponse(OutputStream out, File file) {
      PrintWriter pw = new PrintWriter(out);
      pw.println("HTTP/1.1 200 OK");
      pw.println("Server: Apache-Coyote/1.1");
      pw.println("ETag: W//"6381-1144994988000/"");
      pw.println("Last-Modified: Fri, 14 Apr 2006 06:09:48 GMT");
      pw.println("Content-Type: text/plain");
      pw.println("Content-Length: " + file.length());
 
      DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
           DateFormat.FULL);
      pw.println(df.format(new Date()));
 
      pw.println("Connection: keep-alive");
 
      pw.println("");
      pw.flush();
   }
 
   private void doGet(OutputStream out, String fileName) {
      printOkResponse(out, new File(fileName));
      FileInputStream fis;
      try {
        fis = new FileInputStream(fileName);
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
           out.write(buf, 0, len);
        }
        fis.close();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
 
   }
 
}

完成后,启动我们的服务器程序,客户端浏览器就可以通过我们的IP和80端口访问到我们提供的服务,获取他们想要的web资源啦。